Differential analysis

Protein

Read in all the DPE files calculated by JF Trempe Lab or/and TMT-analyst by RL Files separated by genotype/iPSC line in the workbook “ProcessFilesRenameAccession.Rmd” All data is from 6 weeks DANs from iPSC lines in AIW002-02 background Bright genome and dark genome where run separately

# read in csv into to make a list of dataframes

# Load required library
library(readr)

# the protein DE files are here
folder_path <- "/Users/rhalenathomas/Downloads/Move_Data/DarkGenomeResult/DPE_files/"

# List all CSV files in the folder
csv_files <- list.files(path = folder_path, pattern = "\\.csv$", full.names = TRUE)

# Read all CSV files into a list of dataframes, skipping the first column
df_list <- lapply(csv_files, function(file) {
  read_csv(file, col_types = cols(.default = "?", `...1` = col_skip()))
})
New names:
• `` -> `...1`
New names:
• `` -> `...1`
New names:
• `` -> `...1`
New names:
• `` -> `...1`
New names:
• `` -> `...1`
New names:
• `` -> `...1`
New names:
• `` -> `...1`
New names:
• `` -> `...1`
# Optionally, name each element of the list with the respective file names (without the .csv extension)
names(df_list) <- tools::file_path_sans_ext(basename(csv_files))

# Print the names of the dataframes
print(names(df_list))
[1] "GBA-KO_ProtomicsDifferentialAbundance"    "IGSF9B-KO_ProtomicsDifferentialAbundance" "INPP5F-KO_ProtomicsDifferentialAbundance"
[4] "IP6K2-KO_ProtomicsDifferentialAbundance"  "PINK1-KO_ProtomicsDifferentialAbundance"  "PRKN-KO_ProtomicsDifferentialAbundance"  
[7] "SH3GL2-KO_ProtomicsDifferentialAbundance" "SNCA-A53T_ProtomicsDifferentialAbundance"
# test that these are dataframes

df.gba <- df_list$`GBA-KO_ProtomicsDifferentialAbundance`
head(df.gba)
NA
NA

Rename the list


print(names(df_list))
[1] "GBA-KO"    "IGSF9B-KO" "INPP5F-KO" "IP6K2-KO"  "PINK1-KO"  "PRKN-KO"   "SH3GL2-KO" "SNCA-A53T"
head(df_list$`GBA-KO`)

Volcano plots

Thresholds: Log2 abundance ratio > 0.5 and p value < 0.05


pSH3GL2 <- EnhancedVolcano(df_list$`SH3GL2-KO`,
    lab = df_list$`SH3GL2-KO`$Symbol,
    x = 'log2_ratio',
    y = 'p-value',
    pCutoff = 0.05,
    FCcutoff = 0.5,
    colAlpha = 0.5,
    labSize = 5,
    xlim = c(-3,2.5),
    ylim = c(0, 10.5),
    drawConnectors = FALSE,
    widthConnectors = 0.1,
    max.overlaps = 40,
    legendPosition = "right",
    title = "SH3GL2-KO vs Control",
    subtitle = "Differential Protein Abundance"
   ) + scale_x_continuous(breaks = seq(-3, 2.5, by = 0.5)) +  # Adjust the x-axis breaks as needed
  scale_y_continuous(limits = c(0, 10.5), expand = c(0, 0)) +  # Remove space below the y-axis
  coord_cartesian(xlim = c(-3, 2.5), ylim = c(0, 10.5)) +  # Ensure that the plot does not display points beyond this range
  theme(axis.text.x = element_text(size = 14), axis.text.y = element_text(size = 14))  # Adjust x-axis label size
Scale for x is already present.
Adding another scale for x, which will replace the existing scale.
Scale for y is already present.
Adding another scale for y, which will replace the existing scale.
Coordinate system already present. Adding new coordinate system, which will replace the existing one.
pA53T

pGBA

pPINK1

pPRKN

pIGSF9B

pINPP5F

pIP6K2

pSH3GL2

Make a filtered list of dataframes with the thresholds

colnames(df_list$`GBA-KO`)
[1] "Accession"   "Symbol"      "Description" "log2_ratio"  "p-value"    
head(df_list$`IGSF9B-KO`)

head(df_list_numeric$`IGSF9B-KO`)

filter_dge_lists <- function(dge_lists, logFC_threshold = 0.25, logFC_direction = "both", p_threshold = 0.01, p_col = "p-value") {
  # Iterate over each dataframe in the list
  dge_lists_filtered <- lapply(dge_lists, function(dge_df) {
    # Debugging: Print column names of the dataframe being processed
    print(paste("Processing dataframe with columns:", paste(colnames(dge_df), collapse = ", ")))
    
    # Apply the filter function to each dataframe
    filtered_df <- filter_dge_results(dge_df, logFC_threshold, logFC_direction, p_threshold, p_col)
    
    return(filtered_df)
  })
  
  return(dge_lists_filtered)
}

# Example usage
filtered_DEP <- filter_dge_lists(df_list, logFC_threshold = 0.5, logFC_direction = "both", p_threshold = 0.05, p_col = "p-value")
[1] "Processing dataframe with columns: Accession, Symbol, Description, log2_ratio, p-value"
[1] "Columns in dataframe: Accession, Symbol, Description, log2_ratio, p-value"
[1] "Classes of columns: character, character, character, numeric, numeric"
[1] "Processing dataframe with columns: Accession, Symbol, Description, log2_ratio, p-value"
[1] "Columns in dataframe: Accession, Symbol, Description, log2_ratio, p-value"
[1] "Classes of columns: character, character, character, numeric, numeric"
[1] "Processing dataframe with columns: Accession, Symbol, Description, log2_ratio, p-value"
[1] "Columns in dataframe: Accession, Symbol, Description, log2_ratio, p-value"
[1] "Classes of columns: character, character, character, numeric, numeric"
[1] "Processing dataframe with columns: Accession, Symbol, Description, log2_ratio, p-value"
[1] "Columns in dataframe: Accession, Symbol, Description, log2_ratio, p-value"
[1] "Classes of columns: character, character, character, numeric, numeric"
[1] "Processing dataframe with columns: Accession, Symbol, Description, log2_ratio, p-value"
[1] "Columns in dataframe: Accession, Symbol, Description, log2_ratio, p-value"
[1] "Classes of columns: character, character, character, numeric, numeric"
[1] "Processing dataframe with columns: Accession, Symbol, Description, log2_ratio, p-value"
[1] "Columns in dataframe: Accession, Symbol, Description, log2_ratio, p-value"
[1] "Classes of columns: character, character, character, numeric, numeric"
[1] "Processing dataframe with columns: Accession, Symbol, Description, log2_ratio, p-value"
[1] "Columns in dataframe: Accession, Symbol, Description, log2_ratio, p-value"
[1] "Classes of columns: character, character, character, numeric, numeric"
[1] "Processing dataframe with columns: Accession, Symbol, Description, log2_ratio, p-value"
[1] "Columns in dataframe: Accession, Symbol, Description, log2_ratio, p-value"
[1] "Classes of columns: character, character, character, numeric, numeric"

Get gene counts


# function to count up and down regulated Proteins
count_regulations <- function(dge_df) {
  # Ensure columns are numeric
  dge_df$log2_ratio <- as.numeric(dge_df$log2_ratio)
  
  # Count upregulated and downregulated proteins
  upregulated_count <- sum(dge_df$log2_ratio > 0, na.rm = TRUE)
  downregulated_count <- sum(dge_df$log2_ratio < 0, na.rm = TRUE)
  
  return(c(Upregulated = upregulated_count, Downregulated = downregulated_count))
}

summarize_regulations <- function(dge_lists) {
  # Get names of the dataframes
  df_names <- names(dge_lists)
  
  # Apply the counting function to each dataframe and name the result
  counts_list <- lapply(dge_lists, function(df) {
    counts <- count_regulations(df)
    return(counts)
  })
  
  # Convert the list of counts into a dataframe
  result_df <- do.call(rbind, counts_list)
  
  # Set the row names to the names of the original dataframes
  rownames(result_df) <- df_names
  
  return(result_df)
}

# apply to filtered list
regulation_summary <- summarize_regulations(filtered_DEP)
print(regulation_summary)
          Upregulated Downregulated
GBA-KO            109           137
IGSF9B-KO         559           738
INPP5F-KO         144           209
IP6K2-KO           59            87
PINK1-KO          274           496
PRKN-KO           373           573
SH3GL2-KO         133           116
SNCA-A53T         162           244
colnames(filtered_DEP$`PINK1-KO`)
[1] "Accession"   "Symbol"      "Description" "log2_ratio"  "p-value"    

Function to get the top n genes up and down

# Function to select top n up and down regulated genes
select_top_genes <- function(dge_df, logFC_col = "log2_ratio", symbol_col = "Symbol", n = 10) {
  # Ensure log2_ratio column is numeric
  dge_df[[logFC_col]] <- as.numeric(dge_df[[logFC_col]])
  
  # Sort dataframe by log2_ratio to get top upregulated and downregulated genes
  top_upregulated <- dge_df %>%
    arrange(desc(!!sym(logFC_col))) %>%
    head(n) %>%
    pull(!!sym(symbol_col))
  
  top_downregulated <- dge_df %>%
    arrange(!!sym(logFC_col)) %>%
    head(n) %>%
    pull(!!sym(symbol_col))
  
  # Combine upregulated and downregulated genes into a single vector
  top_genes <- c(top_upregulated, top_downregulated)
  
  return(top_genes)
}

# Example usage
top_genes <- select_top_genes(filtered_DEP$`PINK1-KO`, n = 10)
print(top_genes)
 [1] "NEFL"       "PLXNA4"     "VSNL1"      "NEFM"       "PALM3"      "STX1A"      "ATP5PF"     "SLC25A13"   "SYT2"       "DIRAS2"     "CA2"       
[12] "SNRPA"      "PROCR"      "HDGF"       "A0A087WY61" "ZNF207"     "CD99"       "HMGN3"      "DCN"        "LMNA"      
top_genes <- select_top_genes(filtered_DEP$`PINK1-KO`, n = 5)
print(top_genes)
 [1] "NEFL"       "PLXNA4"     "VSNL1"      "NEFM"       "PALM3"      "CA2"        "SNRPA"      "PROCR"      "HDGF"       "A0A087WY61"

df.pink1 <- filtered_DEP$`PINK1-KO`

Plot a heatmap of the top up and down genes

heatmap_plot <- plot_protein_heatmap(
  data = df,
  proteins = top_genes, # Example protein names
  sample_patterns = c("Control", "PINK1.KO")
)
[1] "Sample columns selected: Control.1, Control.2, Control.3, PINK1.KO.1, PINK1.KO.2, PINK1.KO.3"
# Print the plot
print(heatmap_plot)

Plot control and IPSC line for each list

# Example usage
# Assuming 'df' is your dataframe with relative abundance data
heatmap_plot <- plot_protein_heatmap(
  data = df,
  proteins = top_genes, # Example protein names
  sample_patterns = c("Control", "PINK1.KO")
)
[1] "Sample columns selected: Control.1, Control.2, Control.3, PINK1.KO.1, PINK1.KO.2, PINK1.KO.3"
# Print the plot
print(heatmap_plot)

NA
NA

z-score

#library(ggplot2)
#library(dplyr)
#library(tidyr)

#data = df
#proteins = top_genes
#sample_patterns =  c("Control", "PINK1.KO")

# Function to plot heatmap of relative abundance with Z-scores
plot_protein_heatmap_zscore <- function(data, proteins, sample_patterns, na_color = "grey"){
  # Filter the data for selected proteins
  data_filtered <- data %>%
    filter(Symbol %in% proteins)
  
  # Set the order of the Symbol factor based on the input vector 'proteins'
  data_filtered$Symbol <- factor(data_filtered$Symbol, levels = proteins)

  # Identify sample columns matching patterns
  sample_columns <- colnames(data_filtered)[sapply(colnames(data_filtered), function(col_name) {
    any(sapply(sample_patterns, function(p) grepl(p, col_name)))
  })]

  # Debug: Check contents of sample_columns
  print(paste("Sample columns selected:", paste(sample_columns, collapse = ", ")))

  # Check if sample_columns has valid entries
  if (length(sample_columns) == 0) {
    stop("No sample columns matched the patterns provided.")
  }

  # Select only columns matching sample patterns and the Symbol column
  data_filtered <- data_filtered %>%
    dplyr::select(Symbol, all_of(sample_columns))

  # Remove rows where all values are NA (excluding the Symbol column)
  data_filtered <- data_filtered %>%
    filter(rowSums(is.na(dplyr::select(., -Symbol))) < length(sample_columns))

  # Calculate Z-scores for each protein across the selected samples
  data_zscore <- data_filtered %>%
    mutate(across(all_of(sample_columns), ~ scale(.)[, 1], .names = "z_{col}"))
  # Reshape data for ggplot
  data_long <- data_zscore %>%
    pivot_longer(
      cols = starts_with("z_"), 
      names_to = "Sample", 
      values_to = "Abundance"
    ) %>%
    mutate(Sample = gsub("z_", "", Sample))  # Remove 'z_' prefix for clean sample names
  # Create the heatmap
  heatmap_plot <- ggplot(data_long, aes(x = Sample, y = Symbol, fill = Abundance)) +
    geom_tile(color = "white") +
    scale_fill_gradientn(
    #colors = c("#ffffff", "#ffcccc", "#ff6666", "#ff3333","#fa0505", "#cc0000","#990000"),
    #colors = c("#fdfef4", "#DAF7A6", "#FFC300", "#FF5733","#e71f05","#4d0b02"),
    colors = c("snow","lightgoldenrod1","gold1","darkorange1","red2","firebrick4"),
    values = scales::rescale(c(-0.5, -0.25, 0, 1,2,2.5,2.75)),
    na.value = na_color,
    guide = guide_colorbar(
      barwidth = 1,
      barheight = 10,
      title.position = "top",
      title.hjust = 0.5
    )) +
    theme_minimal() +
    theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
    labs(title = "Protein Abundance Heatmap (Z-Score)", x = "Samples", y = "Proteins")
  
  return(heatmap_plot)
}

# Example usage
heatmap_plot <- plot_protein_heatmap_zscore(
  data = df,
  proteins = top_genes, # Example protein names
  sample_patterns = c("Control", "PINK1.KO")
)
[1] "Sample columns selected: Control.1, Control.2, Control.3, PINK1.KO.1, PINK1.KO.2, PINK1.KO.3"
# Print the plot
print(heatmap_plot)

NA
NA
NA
NA

Adjust the function


library(ggplot2)
library(dplyr)
library(tidyr)

# Function to plot heatmap of relative abundance with Z-scores
plot_protein_heatmap_zscore <- function(data, proteins, sample_patterns, colors, scale_values, na_color = "grey") {
  # Filter the data for selected proteins
  data_filtered <- data %>%
    filter(Symbol %in% proteins)
  
  # Set the order of the Symbol factor based on the input vector 'proteins'
  data_filtered$Symbol <- factor(data_filtered$Symbol, levels = proteins)

  # Identify sample columns matching patterns
  sample_columns <- colnames(data_filtered)[sapply(colnames(data_filtered), function(col_name) {
    any(sapply(sample_patterns, function(p) grepl(p, col_name)))
  })]

  # Debug: Check contents of sample_columns
  print(paste("Sample columns selected:", paste(sample_columns, collapse = ", ")))

  # Check if sample_columns has valid entries
  if (length(sample_columns) == 0) {
    stop("No sample columns matched the patterns provided.")
  }

  # Select only columns matching sample patterns and the Symbol column
  data_filtered <- data_filtered %>%
    dplyr::select(Symbol, all_of(sample_columns))

  # Remove rows where all values are NA (excluding the Symbol column)
  data_filtered <- data_filtered %>%
    filter(rowSums(is.na(dplyr::select(., -Symbol))) < length(sample_columns))

  # Calculate Z-scores for each protein across the selected samples
  data_zscore <- data_filtered %>%
    mutate(across(all_of(sample_columns), ~ scale(.)[, 1], .names = "z_{col}"))

  # Reshape data for ggplot
  data_long <- data_zscore %>%
    pivot_longer(
      cols = starts_with("z_"), 
      names_to = "Sample", 
      values_to = "Abundance"
    ) %>%
    mutate(Sample = gsub("z_", "", Sample))  # Remove 'z_' prefix for clean sample names

  # Create the heatmap
  heatmap_plot <- ggplot(data_long, aes(x = Sample, y = Symbol, fill = Abundance)) +
    geom_tile(color = "white") +
    scale_fill_gradientn(
      colors = colors,
      values = scales::rescale(scale_values),
      na.value = na_color,
      guide = guide_colorbar(
        barwidth = 1,
        barheight = 10,
        title.position = "top",
        title.hjust = 0.5
      )
    ) +
    theme_minimal() +
    theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
    labs(title = "Protein Abundance Heatmap (Z-Score)", x = "Samples", y = "Proteins")
  
  return(heatmap_plot)
}

# Example usage
heatmap_plot <- plot_protein_heatmap_zscore(
  data = df,
  proteins = top_genes, # Example protein names
  sample_patterns = c("Control", "PINK1.KO"),
  colors = c("snow", "lightgoldenrod1", "gold1", "darkorange1", "red2", "firebrick4"),
  scale_values = c(-2.5, -2, -1, 0, 1, 2, 2.5) # Adjust based on your data range
)
[1] "Sample columns selected: Control.1, Control.2, Control.3, PINK1.KO.1, PINK1.KO.2, PINK1.KO.3"
# Print the plot
print(heatmap_plot)

NA
NA

# Example usage
heatmap_plot <- plot_protein_heatmap_zscore(
  data = df,
  proteins = top_genes, # Example protein names
  sample_patterns = c("Control", "PINK1.KO"),
  colors = c("snow", "lightgoldenrod1", "gold1", "darkorange1", "red2", "firebrick4"),
  scale_values = c(-2.5, -2, -1, 0, 1, 2, 2.5), # Adjust based on your data range
  group_means = TRUE # Set to FALSE if you want individual samples
)
[1] "Sample columns selected: Control.1, Control.2, Control.3, PINK1.KO.1, PINK1.KO.2, PINK1.KO.3"
# Print the plot
print(heatmap_plot)



# Example usage
heatmap_plot <- plot_protein_heatmap_zscore(
  data = df,
  proteins = top_genes, # Example protein names
  sample_patterns = c("Control", "PINK1.KO"),
  colors = c("snow", "lightgoldenrod1", "gold1", "darkorange1", "red2", "firebrick4"),
  scale_values = c(-2.5, -2, -1, 0, 1, 2, 2.5), # Adjust based on your data range
  group_means = FALSE # Set to FALSE if you want individual samples
)
[1] "Sample columns selected: Control.1, Control.2, Control.3, PINK1.KO.1, PINK1.KO.2, PINK1.KO.3"
# Print the plot
print(heatmap_plot)

Control width

library(ggplot2)
library(dplyr)
library(tidyr)

# Function to plot heatmap of relative abundance with Z-scores
plot_protein_heatmap_zscore <- function(data, proteins, sample_patterns, colors, scale_values, na_color = "grey", group_means = FALSE, tile_width = 0.9) {
  # Filter the data for selected proteins
  data_filtered <- data %>%
    filter(Symbol %in% proteins)
  
  # Set the order of the Symbol factor based on the input vector 'proteins'
  data_filtered$Symbol <- factor(data_filtered$Symbol, levels = proteins)

  # Identify sample columns matching patterns
  sample_columns <- colnames(data_filtered)[sapply(colnames(data_filtered), function(col_name) {
    any(sapply(sample_patterns, function(p) grepl(p, col_name)))
  })]

  # Debug: Check contents of sample_columns
  print(paste("Sample columns selected:", paste(sample_columns, collapse = ", ")))

  # Check if sample_columns has valid entries
  if (length(sample_columns) == 0) {
    stop("No sample columns matched the patterns provided.")
  }

  # Select only columns matching sample patterns and the Symbol column
  data_filtered <- data_filtered %>%
    dplyr::select(Symbol, all_of(sample_columns))

  # Remove rows where all values are NA (excluding the Symbol column)
  data_filtered <- data_filtered %>%
    filter(rowSums(is.na(dplyr::select(., -Symbol))) < length(sample_columns))

  if (group_means) {
    # Group samples by the base name and calculate mean
    sample_base <- gsub("\\.\\d+$", "", colnames(data_filtered)[-1])
    data_grouped <- data_filtered %>%
      pivot_longer(cols = -Symbol, names_to = "Sample", values_to = "Abundance") %>%
      mutate(SampleBase = gsub("\\.\\d+$", "", Sample)) %>%
      group_by(Symbol, SampleBase) %>%
      summarize(Abundance = mean(Abundance, na.rm = TRUE), .groups = 'drop') %>%
      pivot_wider(names_from = SampleBase, values_from = Abundance)

    # Calculate Z-scores
    data_zscore <- data_grouped %>%
      mutate(across(-Symbol, ~ scale(.)[, 1], .names = "z_{col}"))

    # Reshape data for ggplot
    data_long <- data_zscore %>%
      pivot_longer(
        cols = starts_with("z_"), 
        names_to = "Sample", 
        values_to = "Abundance"
      ) %>%
      mutate(Sample = gsub("z_", "", Sample))  # Remove 'z_' prefix for clean sample names
  } else {
    # Calculate Z-scores for each protein across the selected samples
    data_zscore <- data_filtered %>%
      mutate(across(all_of(sample_columns), ~ scale(.)[, 1], .names = "z_{col}"))

    # Reshape data for ggplot
    data_long <- data_zscore %>%
      pivot_longer(
        cols = starts_with("z_"), 
        names_to = "Sample", 
        values_to = "Abundance"
      ) %>%
      mutate(Sample = gsub("z_", "", Sample))  # Remove 'z_' prefix for clean sample names
  }

  # Create the heatmap
  heatmap_plot <- ggplot(data_long, aes(x = Sample, y = Symbol, fill = Abundance)) +
    geom_tile(color = "white") +
    scale_fill_gradientn(
      colors = colors,
      values = scales::rescale(scale_values),
      na.value = na_color,
      guide = guide_colorbar(
        barwidth = 1,
        barheight = 10,
        title.position = "top",
        title.hjust = 0.5
      )
    ) +
    theme_minimal() +
    theme(
      axis.text.x = element_text(angle = 45, hjust = 1),
      aspect.ratio = 1 / tile_width # Adjust aspect ratio
    ) +
    labs(title = "Protein Abundance Heatmap (Z-Score)", x = "Samples", y = "Proteins")
  
  return(heatmap_plot)
}

# Example usage
heatmap_plot <- plot_protein_heatmap_zscore(
  data = df,
  proteins = top_genes, # Example protein names
  sample_patterns = c("Control", "PINK1.KO"),
  colors = c("snow", "lightgoldenrod1", "gold1", "darkorange1", "red2", "firebrick4"),
  scale_values = c(-2.5, -2, -1, 0, 1, 2, 2.5), # Adjust based on your data range
  group_means = TRUE, # Set to FALSE if you want individual samples
  tile_width = 0.25 # Adjust the width of the tiles (default is 0.9)
)
[1] "Sample columns selected: Control.1, Control.2, Control.3, PINK1.KO.1, PINK1.KO.2, PINK1.KO.3"
# Print the plot
print(heatmap_plot)

NA
NA

Function to see the gene expression

max(df.long$Abundance)
[1] 3.575772
min(df.long$Abundance)
[1] -0.490151

Check each contrast


top_genes <- select_top_genes(filtered_DEP$`PINK1-KO`, n = 10)

plot_protein_heatmap_zscore(
  data = df,
  proteins = top_genes, # Example protein names
  sample_patterns = c("Control", "PINK1.KO"),
  colors = c("snow", "lightgoldenrod1", "gold1", "darkorange1", "red2", "firebrick4"),
  scale_values = c(-0.5, -0.25, 0, 1, 2, 4), # Adjust based on your data range
  group_means = TRUE, # Set to FALSE if you want individual samples
   tile_width = 0.25
)
[1] "Sample columns selected: Control.1, Control.2, Control.3, PINK1.KO.1, PINK1.KO.2, PINK1.KO.3"

plot_protein_heatmap_zscore(
  data = df,
  proteins = top_genes, # Example protein names
  sample_patterns = c("Control", "PINK1.KO"),
  colors = c("snow", "lightgoldenrod1", "gold1", "darkorange1", "red2", "firebrick4"),
  scale_values = c(-0.5, -0.25, 0, 1, 2, 4), # Adjust based on your data range
  group_means = FALSE,# Set to FALSE if you want individual samples
   tile_width = 0.25
)
[1] "Sample columns selected: Control.1, Control.2, Control.3, PINK1.KO.1, PINK1.KO.2, PINK1.KO.3"


plot_protein_heatmap_zscore(
  data = df,
  proteins = top_genes, # Example protein names
  sample_patterns = c("Control", "PINK1.KO"),
  colors = c("snow", "lightgoldenrod1", "gold1", "darkorange1", "red2", "firebrick4"),
  scale_values = c(-0.9,-0.6,-0.2, 0, 2, 2.5), # Adjust based on your data range
  group_means = TRUE, # Set to FALSE if you want individual samples
   tile_width = 0.25
)
[1] "Sample columns selected: Control.1, Control.2, Control.3, PINK1.KO.1, PINK1.KO.2, PINK1.KO.3"

plot_protein_heatmap_zscore(
  data = df,
  proteins = top_genes, # Example protein names
  sample_patterns = c("Control", "PINK1.KO"),
  colors = c("snow", "lightgoldenrod1", "gold1", "darkorange1", "red2", "firebrick4"),
  scale_values = c(-0.9,-0.6,-0.2, 0, 2, 2.5), # Adjust based on your data range
  group_means = FALSE,# Set to FALSE if you want individual samples
   tile_width = 0.25
)
[1] "Sample columns selected: Control.1, Control.2, Control.3, PINK1.KO.1, PINK1.KO.2, PINK1.KO.3"

colnames(df)
 [1] "Symbol"     "A53T.1"     "A53T.2"     "A53T.3"     "Control.1"  "Control.2"  "Control.3"  "GBA.KO.1"   "GBA.KO.2"   "GBA.KO.3"   "PINK1.KO.1"
[12] "PINK1.KO.2" "PINK1.KO.3" "PRKN.KO.1"  "PRKN.KO.2"  "PRKN.KO.3" 

SNCA-A53T


plot_protein_heatmap_zscore(
  data = df,
  proteins = top_genes, # Example protein names
  sample_patterns = c("Control", "A53T"),
  colors = c("snow", "lightgoldenrod1", "gold1", "darkorange1", "red2", "firebrick4"),
  scale_values = c(-1, -0.5,-0.25, 0, 1, 2, 4), # Adjust based on your data range
  group_means = TRUE, # Set to FALSE if you want individual samples
   tile_width = 0.25
)
[1] "Sample columns selected: A53T.1, A53T.2, A53T.3, Control.1, Control.2, Control.3"

plot_protein_heatmap_zscore(
  data = df,
  proteins = top_genes, # Example protein names
  sample_patterns = c("Control", "A53T"),
  colors = c("snow", "lightgoldenrod1", "gold1", "darkorange1", "red2", "firebrick4"),
  scale_values = c(-1, -0.5, -0.25,0, 1, 2, 4), # Adjust based on your data range
  group_means = FALSE,# Set to FALSE if you want individual samples
   tile_width = 0.25
)
[1] "Sample columns selected: A53T.1, A53T.2, A53T.3, Control.1, Control.2, Control.3"

GBA


plot_protein_heatmap_zscore(
  data = df,
  proteins = top_genes, # Example protein names
  sample_patterns = c("Control", "GBA.KO"),
  colors = c("snow", "lightgoldenrod1", "gold1", "darkorange1", "red2", "firebrick4"),
  scale_values = c(-1, -0.5, -0.25,0, 1, 2, 3.5), # Adjust based on your data range
  group_means = TRUE, # Set to FALSE if you want individual samples
   tile_width = 0.25
)
[1] "Sample columns selected: Control.1, Control.2, Control.3, GBA.KO.1, GBA.KO.2, GBA.KO.3"

plot_protein_heatmap_zscore(
  data = df,
  proteins = top_genes, # Example protein names
  sample_patterns = c("Control", "GBA.KO"),
  colors = c("snow", "lightgoldenrod1", "gold1", "darkorange1", "red2", "firebrick4"),
  scale_values = c(-1, -0.5, -0.25,0, 1, 2, 3.5), # Adjust based on your data range
  group_means = FALSE,# Set to FALSE if you want individual samples
   tile_width = 0.25
)
[1] "Sample columns selected: Control.1, Control.2, Control.3, GBA.KO.1, GBA.KO.2, GBA.KO.3"

Parkin KO


plot_protein_heatmap_zscore(
  data = df,
  proteins = top_genes, # Example protein names
  sample_patterns = c("Control", "PRKN.KO"),
  colors = c("snow", "lightgoldenrod1", "gold1", "darkorange1", "red2", "firebrick4"),
  scale_values = c(-1, -0.5, -0.25,0, 1, 2, 3.5), # Adjust based on your data range
  group_means = TRUE, # Set to FALSE if you want individual samples
   tile_width = 0.25
)
[1] "Sample columns selected: Control.1, Control.2, Control.3, PRKN.KO.1, PRKN.KO.2, PRKN.KO.3"

plot_protein_heatmap_zscore(
  data = df,
  proteins = top_genes, # Example protein names
  sample_patterns = c("Control", "PRKN.KO"),
  colors = c("snow", "lightgoldenrod1", "gold1", "darkorange1", "red2", "firebrick4"),
  scale_values = c(-1, -0.5, -0.25,0, 1, 2, 3.5), # Adjust based on your data range
  group_means = FALSE,# Set to FALSE if you want individual samples
   tile_width = 0.25
)
[1] "Sample columns selected: Control.1, Control.2, Control.3, PRKN.KO.1, PRKN.KO.2, PRKN.KO.3"

For the dark genome gene expression levels I’ll need the other dataframe

colnames(df)
 [1] "Symbol"      "Control.1"   "Control.2"   "Control.3"   "Control.4"   "IGSF9B.KO.1" "IGSF9B.KO.2" "INPP5F.KO.1" "INPP5F.KO.2" "INPP5F.KO.3"
[11] "IP6K2.KO.1"  "IP6K2.KO.2"  "IP6K2.KO.4"  "SH3GL2.KO.1" "SH3GL2.KO.2" "SH3GL2.KO.3"

plot_protein_heatmap_zscore(
  data = df,
  proteins = top_genes, # Example protein names
  sample_patterns = c("Control", "IGSF9B.KO"),
  colors = c("snow", "lightgoldenrod1", "gold1", "darkorange1", "red2", "firebrick4"),
  scale_values = c(-1, -0.5, -0.25,0, 1, 2, 3.5), # Adjust based on your data range
  group_means = TRUE, # Set to FALSE if you want individual samples
   tile_width = 0.25
)
[1] "Sample columns selected: Control.1, Control.2, Control.3, Control.4, IGSF9B.KO.1, IGSF9B.KO.2"

plot_protein_heatmap_zscore(
  data = df,
  proteins = top_genes, # Example protein names
  sample_patterns = c("Control", "IGSF9B.KO"),
  colors = c("snow", "lightgoldenrod1", "gold1", "darkorange1", "red2", "firebrick4"),
  scale_values = c(-1, -0.5, -0.25,0, 1, 2, 3.5), # Adjust based on your data range
  group_means = FALSE,# Set to FALSE if you want individual samples
   tile_width = 0.25
)
[1] "Sample columns selected: Control.1, Control.2, Control.3, Control.4, IGSF9B.KO.1, IGSF9B.KO.2"


plot_protein_heatmap_zscore(
  data = df,
  proteins = top_genes, # Example protein names
  sample_patterns = c("Control", "INPP5F.KO"),
  colors = c("snow", "lightgoldenrod1", "gold1", "darkorange1","red", "red2", "firebrick4"),
  scale_values = c(-0.75, -0.5, -0.25,0, 1, 2, 4), # Adjust based on your data range
  group_means = TRUE, # Set to FALSE if you want individual samples
   tile_width = 0.25
)
[1] "Sample columns selected: Control.1, Control.2, Control.3, Control.4, INPP5F.KO.1, INPP5F.KO.2, INPP5F.KO.3"

plot_protein_heatmap_zscore(
  data = df,
  proteins = top_genes, # Example protein names
  sample_patterns = c("Control", "INPP5F.KO"),
  colors = c("snow", "lightgoldenrod1", "gold1", "darkorange1","red", "red2", "firebrick4"),
  scale_values = c(-0.75, -0.5, -0.25,0, 1, 2, 4), # Adjust based on your data range
  group_means = FALSE,# Set to FALSE if you want individual samples
   tile_width = 0.25
)
[1] "Sample columns selected: Control.1, Control.2, Control.3, Control.4, INPP5F.KO.1, INPP5F.KO.2, INPP5F.KO.3"


plot_protein_heatmap_zscore(
  data = df,
  proteins = top_genes, # Example protein names
  sample_patterns = c("Control", "IP6K2.KO"),
  colors = c("snow", "lightgoldenrod1", "gold1", "darkorange1","red", "red2", "firebrick4"),
  scale_values = c(-0.75, -0.5, -0.25,0, 1, 2, 4), # Adjust based on your data range
  group_means = TRUE, # Set to FALSE if you want individual samples
   tile_width = 0.25
)
[1] "Sample columns selected: Control.1, Control.2, Control.3, Control.4, IP6K2.KO.1, IP6K2.KO.2, IP6K2.KO.4"

plot_protein_heatmap_zscore(
  data = df,
  proteins = top_genes, # Example protein names
  sample_patterns = c("Control", "IP6K2.KO"),
  colors = c("snow", "lightgoldenrod1", "gold1", "darkorange1","red", "red2", "firebrick4"),
  scale_values = c(-0.75, -0.5, -0.25,0, 1, 2, 4), # Adjust based on your data range
  group_means = FALSE,# Set to FALSE if you want individual samples
   tile_width = 0.25
)
[1] "Sample columns selected: Control.1, Control.2, Control.3, Control.4, IP6K2.KO.1, IP6K2.KO.2, IP6K2.KO.4"

plot_protein_heatmap_zscore(
  data = df,
  proteins = top_genes, # Example protein names
  sample_patterns = c("Control", "SH3GL2.KO"),
  colors = c("snow", "lightgoldenrod1", "gold1", "darkorange1","red", "red2", "firebrick4"),
  scale_values = c(-0.6, -0.5,0.25, 0, 1, 3.8, 4.1), # Adjust based on your data range
  group_means = TRUE, # Set to FALSE if you want individual samples
   tile_width = 0.25
)
[1] "Sample columns selected: Control.1, Control.2, Control.3, Control.4, SH3GL2.KO.1, SH3GL2.KO.2, SH3GL2.KO.3"

plot_protein_heatmap_zscore(
  data = df,
  proteins = top_genes, # Example protein names
  sample_patterns = c("Control", "SH3GL2.KO"),
  colors = c("snow", "lightgoldenrod1", "gold1", "darkorange1","red", "red2", "firebrick4"),
  scale_values = c(-0.6, -0.5,0.25, 0, 1, 3.8, 4.1), # Adjust based on your data range
  group_means = FALSE,# Set to FALSE if you want individual samples
   tile_width = 0.25
)
[1] "Sample columns selected: Control.1, Control.2, Control.3, Control.4, SH3GL2.KO.1, SH3GL2.KO.2, SH3GL2.KO.3"

names(filtered_DEP)
[1] "GBA-KO"    "IGSF9B-KO" "INPP5F-KO" "IP6K2-KO"  "PINK1-KO"  "PRKN-KO"   "SH3GL2-KO" "SNCA-A53T"

gene overlap


# Create the UpSet plot
upset(
  gene_matrix,
  sets = names(gene_lists),
  sets.bar.color = "#56B4E9",
  order.by = "freq",
  empty.intersections = "on",
  keep.order = TRUE
)

Control the order


p <- create_upset_plot(filtered_DEP, contrast_order, colors = rev(colors), text_scale = 1.5)
'data.frame':   2314 obs. of  9 variables:
 $ Symbol   : chr  "HDLBP" "EHD1" "OSTC" "VTA1" ...
 $ IP6K2-KO : num  0 0 0 0 0 0 0 0 0 0 ...
 $ SH3GL2-KO: num  0 0 0 0 0 0 0 0 0 0 ...
 $ INPP5F-KO: num  0 0 0 0 0 0 0 0 0 0 ...
 $ IGSF9B-KO: num  0 0 1 1 1 0 1 0 0 1 ...
 $ PRKN-KO  : num  1 1 0 1 0 0 1 0 1 1 ...
 $ PINK1-KO : num  1 1 1 1 0 0 1 0 1 1 ...
 $ GBA-KO   : num  1 1 1 1 1 1 1 1 1 1 ...
 $ SNCA-A53T: num  1 0 1 0 0 0 1 1 1 1 ...
NULL
print(p)

pdf("/Users/rhalenathomas/Downloads/Move_Data/DarkGenomeResult/omics/UpsetplotBrightandDark.pdf", width = 10, height = 5.5)
p
dev.off()
null device 
          1 

See which genes overlap - function

# bright genome overlap
contrast_list <- c("SNCA-A53T", "GBA-KO", "PINK1-KO","PRKN-KO") # Specify the contrasts of interest

result.bright <- get_gene_overlap_and_unique(filtered_DEP, contrast_list)

# Print results
print(result.bright$`Overlapping Genes`) # Genes common across all specified contrasts
  [1] "HDLBP"      "NCAM1"      "A0A0J9YYL3" "STXBP1"     "A0A1P0AYU5" "RPS14"      "PALM3"      "HSPA12A"    "PRKRA"      "P4HB"       "OBSCN"     
 [12] "SNRPE"      "SCFD1"      "CYCS"       "CTSD"       "RPS3A"      "SNCA"       "NEFM"       "TP53I11"    "F8W6I7"     "CD44"       "H3BQZ7"    
 [23] "CBX1"       "SLC16A3"    "HNRNPUL1"   "C11orf58"   "VGF"        "DCX"        "KPNA6"      "CLN5"       "SNCG"       "LY6H"       "HRAS"      
 [34] "FUCA1"      "ANXA1"      "ATP1B1"     "SSB"        "KRT18"      "PYGL"       "NEFL"       "ANXA2"      "DCN"        "SYP"        "ANXA5"     
 [45] "GSTP1"      "GNAO1"      "HSPA5"      "RALA"       "ATP1A3"     "P4HA1"      "GNS"        "PPP3CB"     "SYN1"       "GAP43"      "NCL"       
 [56] "FLNA"       "MAOA"       "HNRNPA2B1"  "ATP2B4"     "FKBP2"      "EPHB2"      "EEF1D"      "CRABP1"     "PRDX6"      "LRPAP1"     "RPS19"     
 [67] "PRPH"       "ACAA2"      "SRP9"       "SERPINH1"   "HDGF"       "RPS8"       "RPS23"      "RPS13"      "RPL23A"     "GNB1"       "RPL10A"    
 [78] "ABAT"       "ERH"        "SET"        "PLOD1"      "NUCB1"      "CRYZ"       "LGALS3BP"   "AHNAK"      "GALNT2"     "CNTN1"      "DNAJC3"    
 [89] "TRIM28"     "ALCAM"      "STX1A"      "FNDC3B"     "GDAP1L1"    "CEP68"      "CEND1"      "CADM2"      "GLG1"       "CMBL"       "DIRAS2"    
[100] "FUCA2"      "GOLPH3"     "CTPS2"      "TMOD3"      "NTM"        "RRBP1"      "PLXNA1"     "SEC23IP"   
#print(result$`Unique Genes`) # List of genes unique to each contrast

Function isn’t exactly correct need to fix

intersect(pink.df$Accession, prkn.df$Accession)
  [1] "A0A024R4E5" "A0A024R571" "A0A087WTT1" "A0A087WWD4" "A0A087WWU8" "A0A087WY55" "A0A0A0MQX8" "A0A0A6YYA0" "A0A0D9SF30" "A0A0D9SF98" "A0A0J9YXF2"
 [12] "A0A0J9YYL3" "A0A1B0GTP9" "A0A1P0AYU5" "A0A1W2PQR6" "A0A2R8Y5S7" "A0A2R8Y6W5" "A0A2R8Y811" "A0A2R8Y849" "A0A2R8YDT1" "A0A3B3IU69" "A0A494BWY4"
 [23] "A0A494C1E2" "A0A590UJ23" "A0A5F9UP49" "A0A5F9ZHL1" "A0A669KB89" "A0A6I8PIW1" "A0A6Q8PFE5" "A0A6Q8PFJ0" "A0A6Q8PGS2" "A0A7I2V3I2" "A0A7I2V4B3"
 [34] "A0A7I2V4E4" "A0A7I2V535" "A0A7I2V5H3" "A0A7I2YQT2" "A0A7P0PJI2" "A0A7P0TA35" "A0A7P0TA76" "A0A7P0TAG7" "A0A7P0TAQ9" "A0A804HK65" "A0A804HL40"
 [45] "A2A2V1"     "A6NFX8"     "A6NGQ3"     "A6NHK2"     "A6NNK5"     "A8MU27"     "A8MXP9"     "B0QZK4"     "B1ALY0"     "B3KS98"     "B4DHE8"    
 [56] "B4DLN1"     "B4DLR8"     "B5ME19"     "B7Z5N7"     "B7ZC39"     "C9J3D7"     "C9J813"     "C9JFR7"     "C9JH19"     "C9JZR2"     "D6RAT0"    
 [67] "D6REX3"     "D6RH20"     "E2QRB3"     "E7EPV7"     "E7ESP9"     "E7EUC7"     "E7EX17"     "E7EX73"     "E9PC15"     "E9PDF2"     "E9PF59"    
 [78] "E9PFH4"     "E9PHY5"     "E9PIN5"     "E9PJP2"     "E9PNF7"     "F5GWR7"     "F5GYQ1"     "F5GZS6"     "F8VW96"     "F8VZX2"     "F8W6I7"    
 [89] "G3V0I5"     "G3V186"     "G3V1L9"     "G3V3E8"     "H0Y3P2"     "H0Y938"     "H0YD13"     "H0YHX9"     "H0YKD8"     "H3BN98"     "H3BQZ7"    
[100] "H3BQZ9"     "H3BUF6"     "H7BZJ3"     "H7C1N3"     "H7C2N1"     "H9KV31"     "J3KNP2"     "J3KS05"     "J3KS31"     "J3QQV2"     "K7ELL7"    
[111] "K7ENE8"     "K7ERC8"     "M0R0F0"     "M0R181"     "M0R210"     "M0R3F1"     "O00193"     "O00425"     "O00461"     "O00625"     "O00754"    
[122] "O15240"     "O43143"     "O43175"     "O43181"     "O43242"     "O43399"     "O43602"     "O43615"     "O43639"     "O43684"     "O60313"    
[133] "O60684"     "O60763"     "O60831"     "O60841"     "O75306"     "O75368"     "O75369"     "O75390"     "O75475"     "O75489"     "O75503"    
[144] "O75525"     "O75718"     "O75746"     "O76003"     "O76070"     "O94772"     "O94826"     "O94925"     "O95197"     "O95302"     "O95336"    
[155] "O95631"     "P00390"     "P00403"     "P00505"     "P00738"     "P01112"     "P02786"     "P04066"     "P04080"     "P04083"     "P04181"    
[166] "P04843"     "P05026"     "P05204"     "P05413"     "P05455"     "P05783"     "P05787"     "P05937"     "P06737"     "P06756"     "P07196"    
[177] "P07355"     "P07585"     "P07858"     "P07954"     "P08247"     "P08670"     "P08758"     "P08865"     "P09211"     "P09471"     "P09874"    
[188] "P09960"     "P09972"     "P10155"     "P10253"     "P10909"     "P11021"     "P11233"     "P11279"     "P11413"     "P12004"     "P12036"    
[199] "P12532"     "P13010"     "P13637"     "P13667"     "P13674"     "P14406"     "P15289"     "P15586"     "P15880"     "P16152"     "P16278"    
[210] "P16298"     "P16615"     "P16671"     "P17050"     "P17600"     "P17677"     "P18077"     "P18859"     "P19338"     "P19367"     "P20020"    
[221] "P20073"     "P20962"     "P21283"     "P21333"     "P21397"     "P21796"     "P21912"     "P22307"     "P22626"     "P23396"     "P23526"    
[232] "P23634"     "P24539"     "P25398"     "P25705"     "P25788"     "P26012"     "P26232"     "P26373"     "P26641"     "P26885"     "P26992"    
[243] "P27635"     "P27797"     "P29323"     "P29401"     "P29692"     "P29762"     "P30041"     "P30044"     "P30533"     "P30536"     "P30837"    
[254] "P31689"     "P32004"     "P32189"     "P32969"     "P35221"     "P35240"     "P36542"     "P37108"     "P37837"     "P38435"     "P39019"    
[265] "P39023"     "P40261"     "P40926"     "P41219"     "P42765"     "P43121"     "P43155"     "P45973"     "P46783"     "P46940"     "P46977"    
[276] "P48444"     "P48681"     "P49189"     "P49458"     "P49755"     "P49915"     "P50148"     "P50454"     "P50995"     "P51571"     "P51572"    
[287] "P51798"     "P51858"     "P52306"     "P52655"     "P52788"     "P52815"     "P53396"     "P53618"     "P53621"     "P54709"     "P54727"    
[298] "P54802"     "P55036"     "P55809"     "P58876"     "P59768"     "P60033"     "P60174"     "P60842"     "P60866"     "P60880"     "P61224"    
[309] "P61764"     "P62081"     "P62241"     "P62266"     "P62269"     "P62277"     "P62701"     "P62750"     "P62760"     "P62873"     "P62888"    
[320] "P62906"     "P63096"     "P63220"     "P63244"     "P67936"     "P68104"     "P78357"     "P78527"     "P80303"     "P80404"     "P80723"    
[331] "P83731"     "P84090"     "Q00577"     "Q00688"     "Q01105"     "Q01581"     "Q02809"     "Q02818"     "Q06323"     "Q08209"     "Q08211"    
[342] "Q08257"     "Q08380"     "Q09666"     "Q10471"     "Q12841"     "Q12860"     "Q12907"     "Q13217"     "Q13263"     "Q13310"     "Q13442"    
[353] "Q13740"     "Q14152"     "Q14315"     "Q15019"     "Q15102"     "Q15149"     "Q15365"     "Q15369"     "Q15424"     "Q15555"     "Q15651"    
[364] "Q15768"     "Q16186"     "Q16352"     "Q16531"     "Q16623"     "Q16778"     "Q32P28"     "Q4J6C6"     "Q53EP0"     "Q5JXI8"     "Q5SQI0"    
[375] "Q5SW79"     "Q5SWX8"     "Q5T1M5"     "Q5T760"     "Q5T7C4"     "Q5TE61"     "Q5URX0"     "Q5ZPR3"     "Q60FE5"     "Q6DKJ4"     "Q6P587"    
[386] "Q6X4W1"     "Q76N32"     "Q7KZF4"     "Q7L0Y3"     "Q7Z4G1"     "Q86TU7"     "Q86UY8"     "Q8N111"     "Q8N3J6"     "Q8N8L6"     "Q8NBU5"    
[397] "Q8NC51"     "Q8TAT6"     "Q8TB37"     "Q8TCJ2"     "Q8WVV9"     "Q8WXD2"     "Q92743"     "Q92859"     "Q92879"     "Q92896"     "Q92945"    
[408] "Q969H8"     "Q969X5"     "Q96AQ6"     "Q96AX1"     "Q96AY3"     "Q96CW9"     "Q96DA6"     "Q96DG6"     "Q96E17"     "Q96E39"     "Q96FJ2"    
[419] "Q96HU8"     "Q96I24"     "Q96N66"     "Q96QR8"     "Q96RD7"     "Q96T51"     "Q99460"     "Q99471"     "Q99733"     "Q99747"     "Q9BPW8"    
[430] "Q9BRX8"     "Q9BTY2"     "Q9BUH6"     "Q9BVM2"     "Q9BW30"     "Q9BYD2"     "Q9BYT8"     "Q9BZ95"     "Q9H0A8"     "Q9H115"     "Q9H1E3"    
[441] "Q9H1K0"     "Q9H3N1"     "Q9H492"     "Q9H4A6"     "Q9H845"     "Q9H8Y8"     "Q9H910"     "Q9H936"     "Q9H9J2"     "Q9HAS0"     "Q9HAV4"    
[452] "Q9HAV7"     "Q9HCJ6"     "Q9NQ48"     "Q9NQ66"     "Q9NRF8"     "Q9NRX4"     "Q9NSE4"     "Q9NVI7"     "Q9NX76"     "Q9NXG6"     "Q9NY47"    
[463] "Q9NYL9"     "Q9NZ53"     "Q9NZ72"     "Q9NZI8"     "Q9P016"     "Q9P032"     "Q9P0J0"     "Q9P0V9"     "Q9P121"     "Q9P1W3"     "Q9P2E9"    
[474] "Q9UBT2"     "Q9UEL6"     "Q9UEY8"     "Q9UHB9"     "Q9UHL4"     "Q9UII2"     "Q9UIV1"     "Q9UIW2"     "Q9UJS0"     "Q9UK22"     "Q9UKY7"    
[485] "Q9ULH1"     "Q9UMX5"     "Q9UNN8"     "Q9UQ80"     "Q9Y277"     "Q9Y2B0"     "Q9Y2J2"     "Q9Y2X3"     "Q9Y3D6"     "Q9Y3I0"     "Q9Y490"    
[496] "Q9Y512"     "Q9Y5B9"     "Q9Y5L4"     "Q9Y5P6"     "Q9Y678"     "Q9Y680"     "Q9Y6M1"     "Q9Y6Y8"    
# apply to filtered list
regulation_summary <- summarize_regulations(filtered_DEP)
print(regulation_summary)
          Upregulated Downregulated
GBA-KO            109           137
IGSF9B-KO         559           738
INPP5F-KO         144           209
IP6K2-KO           59            87
PINK1-KO          274           496
PRKN-KO           373           573
SH3GL2-KO         133           116
SNCA-A53T         162           244
contrast_list <- c("SNCA-A53T", "GBA-KO", "PINK1-KO","PRKN-KO","IGSF9B-KO","INPP5F-KO","IP6K2-KO","IGSF9B-KO", "INPP5F-KO", "IP6K2-KO") # Specify the contrasts of interest

all <- get_gene_overlap_and_unique(filtered_DEP, contrast_list)
print(all$`Overlapping Genes`)
names(filtered_DEP)
[1] "GBA-KO"    "IGSF9B-KO" "INPP5F-KO" "IP6K2-KO"  "PINK1-KO"  "PRKN-KO"   "SH3GL2-KO" "SNCA-A53T"
print(gba.pink1)
$`Overlapping Genes`
  [1] "HDLBP"      "EHD1"       "OSTC"       "VTA1"       "NCAM1"      "A0A0J9YYL3" "STXBP1"     "A0A1P0AYU5" "HNRNPU"     "RPL5"       "RPS14"     
 [12] "SMARCE1"    "A0A3B3IRQ9" "PALM3"      "HSPA12A"    "LMNA"       "PRKRA"      "P4HB"       "OBSCN"      "SNRPE"      "EWSR1"      "B4DLN1"    
 [23] "HNRNPC"     "B4E171"     "SCFD1"      "CALD1"      "CYCS"       "CTSD"       "RPS3A"      "SNCA"       "NEFM"       "HNRNPH1"    "TP53I11"   
 [34] "PRCP"       "ATP6V0D1"   "F8W6I7"     "CD44"       "H3BQZ7"     "APRT"       "ATXN2L"     "HMGN1"      "NCAM2"      "RPL17"      "CBX1"      
 [45] "DDX5"       "SLC16A3"    "SF3A2"      "HNRNPUL1"   "ACOT7"      "C11orf58"   "MAN2B1"     "DPYSL4"     "VGF"        "SYT7"       "DCX"       
 [56] "KPNA6"      "CS"         "PSIP1"      "NDUFS3"     "CLN5"       "GLRX3"      "SNCG"       "CIAO1"      "LY6H"       "TOMM70"     "DIRAS1"    
 [67] "HSPA4L"     "TXNDC12"    "GOT2"       "CA2"        "HRAS"       "FUCA1"      "ANXA1"      "OAT"        "ATP1B1"     "HMGN2"      "FABP3"     
 [78] "SSB"        "KRT18"      "PYGL"       "NEFL"       "ANXA2"      "DCN"        "FH"         "ANXA6"      "SYP"        "VIM"        "ANXA5"     
 [89] "GSTP1"      "GNAO1"      "HSPA5"      "RALA"       "XRCC6"      "ATP1A3"     "PDIA4"      "P4HA1"      "SNRPB"      "HNRNPL"     "EZR"       
[100] "GNS"        "PPP3CB"     "NAGA"       "SYN1"       "GAP43"      "ATP5PF"     "NCL"        "HK1"        "LMNB1"      "FLNA"       "MAOA"      
[111] "VDAC1"      "HNRNPA2B1"  "ATP2B4"     "ATP5PB"     "FKBP2"      "CALR"       "EPHB2"      "EEF1D"      "CRABP1"     "PRDX6"      "LRPAP1"    
[122] "TSPO"       "ALDH1B1"    "GK"         "RPS19"      "PRPH"       "ACAA2"      "CBX5"       "ALDH9A1"    "FASN"       "SRP9"       "SERPINB9"  
[133] "SERPINH1"   "GPM6A"      "HDGF"       "STX1B"      "RPS8"       "RPS23"      "RPS13"      "RPL23A"     "RPL23"      "GNB1"       "RPL10A"    
[144] "ABAT"       "ERH"        "SET"        "HMGCS1"     "PLOD1"      "NUCB1"      "RPL6"       "CRYZ"       "LGALS3BP"   "NCBP1"      "AHNAK"     
[155] "GALNT2"     "FSTL1"      "CNTN1"      "DNAJC3"     "TRIM28"     "PDAP1"      "ALCAM"      "FLNC"       "PLEC"       "CNN3"       "SNCB"      
[166] "STX1A"      "FNDC3B"     "HMGB1"      "GDAP1L1"    "NXN"        "FAHD1"      "CEP68"      "KTN1"       "CEND1"      "CADM2"      "SYT2"      
[177] "SERBP1"     "PLBD2"      "NUBPL"      "CELF1"      "GLG1"       "ATP6V0A1"   "CMBL"       "RAB3C"      "DIRAS2"     "FUBP3"      "RBM17"     
[188] "SCN2A"      "SEPTIN5"    "NAPG"       "DPYSL5"     "FUCA2"      "MAP1LC3A"   "GOLPH3"     "JPT2"       "SLC25A22"   "CTPS2"      "PHPT1"     
[199] "TMOD3"      "SEPTIN10"   "NTM"        "RRBP1"      "UBA2"       "ADD3"       "PLXNA1"     "SLC25A13"   "NENF"       "THRAP3"     "SAMM50"    
[210] "SUPT16H"    "SEC23IP"   

$`Unique Genes`
$`Unique Genes`$`GBA-KO`
 [1] "SNX12"      "MADD"       "A0A0G2JLB3" "C9JIZ6"     "IDH3G"      "SPARC"      "NRXN2"      "BAIAP2"     "YES1"       "PLXNC1"     "SLC25A5"   
[12] "SCG2"       "ATP6V1B2"   "COMT"       "ITGA6"      "MAOB"       "SDHA"       "RPL4"       "PLCB3"      "SELENBP1"   "NNT"        "ELAVL3"    
[23] "QPRT"       "RHEB"       "MRPL23"     "HSDL1"      "RELL2"      "ABCF1"      "SMARCC2"    "RAPGEF4"    "RMDN1"      "MAP7D2"     "GDA"       

$`Unique Genes`$`PINK1-KO`
  [1] "A0A087WTM1"   "PABPC1"       "CLTC"         "TPM3"         "A0A087WY61"   "TARDBP"       "SRSF3"        "CD99"         "MYEF2"       
 [10] "MBNL1"        "A0A0A0MR09"   "NOLC1"        "GSN"          "ILK"          "TMED7-TICAM2" "PON2"         "ENAH"         "QARS1"       
 [19] "SCARB2"       "SEPTIN3"      "RDX"          "MEA1"         "RPS24"        "GLUL"         "MOGS"         "EML1"         "TMEM132E"    
 [28] "PGM3"         "DLG1"         "AP3B2"        "A0A5F9UP49"   "ACAT1"        "DDX17"        "SCRIB"        "TCOF1"        "CAST"        
 [37] "GDAP1"        "UBE3A"        "TRIM2"        "EIF3E"        "ADAM9"        "EIF4H"        "NONO"         "PPIG"         "NPM1"        
 [46] "SYNCRIP"      "PITRM1"       "SRP54"        "ACSL3"        "SLC1A3"       "DNAJC10"      "RMND1"        "HSD17B4"      "RABGAP1L"    
 [55] "CRELD1"       "LRPPRC"       "IARS1"        "SHTN1"        "A2A2V1"       "NUDT5"        "PTBP1"        "TP53BP1"      "SUMO3"       
 [64] "MATR3"        "HP1BP3"       "PALM2AKAP2"   "EIF3H"        "MSI2"         "NQO1"         "ILF2"         "PREB"         "EIF3CL"      
 [73] "SH3GLB2"      "CROT"         "CTNND1"       "PLRG1"        "HNRNPAB"      "SEC31A"       "MRPS27"       "CIRBP"        "PYCR1"       
 [82] "SKP1"         "SDC2"         "UGP2"         "EIF4B"        "EIF4G1"       "ALYREF"       "AGK"          "CELF2"        "OGDH"        
 [91] "DPP6"         "TNPO3"        "ADCYAP1R1"    "EPB41L2"      "E9PJP2"       "HSPA8"        "UBTF"         "RPL8"         "PTPRD"       
[100] "SLC3A2"       "LAMTOR1"      "CSRP2"        "PCBP2"        "UBAP2L"       "F8WE88"       "NDUFV1"       "GRID1"        "TJP1"        
[109] "NPC2"         "ARFGAP2"      "H0Y3P2"       "COPB2"        "NACA"         "RPL28"        "H3BN98"       "PDIA3"        "BET1"        
[118] "PTMA"         "TBL3"         "RPL36A"       "TMEM199"      "ZNF207"       "SRSF1"        "PRKCSH"       "FXYD7"        "FARSA"       
[127] "KDSR"         "GPX4"         "RPS5"         "RPL21"        "RPS16"        "RPL18A"       "HIP1"         "IGF2BP3"      "GOLIM4"      
[136] "HMGN4"        "PIR"          "LIN7A"        "HNRNPDL"      "DCLK1"        "DHX15"        "RNMT"         "PHGDH"        "NDUFS4"      
[145] "DYNC1LI2"     "PSMD3"        "HNRNPR"       "TPD52L2"      "TGOLN2"       "TIMM44"       "CHMP2A"       "NCK2"         "BUB3"        
[154] "AHCYL1"       "SPAG9"        "OPA1"         "SNAP91"       "PLIN3"        "USO1"         "PRAF2"        "EIF5B"        "NDUFS2"      
[163] "SH3BGRL"      "FLNB"         "SEC22B"       "KHDRBS3"      "SF3B1"        "CRTAP"        "SLC25A12"     "IDH1"         "CPD"         
[172] "SEC24D"       "UFL1"         "ABCA8"        "GLS"          "AP2A2"        "RTN3"         "FKBP9"        "PGLS"         "NTN1"        
[181] "GSR"          "COX2"         "HP"           "KRAS"         "TFRC"         "CSTB"         "TUBB4A"       "RPN1"         "FGF1"        
[190] "RPLP0"        "PRKCB"        "KRT8"         "CALB1"        "GPI"          "ITGAV"        "EPRS1"        "CTSB"         "HSP90AA1"    
[199] "PFKM"         "SNRPB2"       "RPSA"         "SNRPA"        "PARP1"        "LTA4H"        "ALDOC"        "RO60"         "GAA"         
[208] "H1-4"         "CLU"          "PYGB"         "LAMP1"        "G6PD"         "PCNA"         "NEFH"         "CKMT1B"       "CKMT1A"      
[217] "XRCC5"        "COX7A2"       "HSP90B1"      "DARS1"        "ARSA"         "RPS2"         "CBR1"         "GLB1"         "ATP2A2"      
[226] "CD36"         "DES"          "RPL35A"       "ATP2B1"       "ANXA7"        "RAB3A"        "PTMS"         "ATP6V1C1"     "SDHB"        
[235] "SCP2"         "IGFBP4"       "SFPQ"         "RPS3"         "AHCY"         "RPS12"        "ATP5F1A"      "PSMA3"        "ITGB8"       
[244] "DDX6"         "CTNNA2"       "RPL13"        "EEF1G"        "CNTFR"        "RPL10"        "MAP4"         "GRN"          "TKT"         
[253] "PRDX5"        "RPL12"        "CORO1A"       "DNAJA1"       "HNRNPH3"      "YWHAB"        "L1CAM"        "SLC8A1"       "RPL9"        
[262] "HSPA4"        "CTNNA1"       "NF2"          "RPL22"        "FUS"          "ATP5F1C"      "ATP6V1E1"     "SRP14"        "TALDO1"      
[271] "GGCX"         "ATP6V1A"      "RPL3"         "NNMT"         "USP8"         "MDH2"         "RPL35"        "PAFAH1B1"     "MCAM"        
[280] "CRAT"         "NSF"          "RPS9"         "RPS10"        "IQGAP1"       "STT3A"        "ARCN1"        "LSS"          "NES"         
[289] "LMAN1"        "ACADVL"       "TMED10"       "GMPS"         "GNAQ"         "ANXA11"       "SSR4"         "BCAP31"       "CLCN7"       
[298] "HNRNPA3"      "HNRNPM"       "RAP1GDS1"     "GTF2A1"       "SMS"          "MRPL12"       "HMGA2"        "ACLY"         "COPB1"       
[307] "COPA"         "ATP1B3"       "RAD23B"       "NAGLU"        "PSMD4"        "OXCT1"        "MARS1"        "EIF6"         "H2BC5"       
[316] "GNG2"         "CD81"         "TPI1"         "EIF4A1"       "RPS20"        "SNAP25"       "RAP1B"        "RPL26"        "NUTF2"       
[325] "HNRNPK"       "RPS7"         "PPP1CB"       "RPS18"        "RPS11"        "SNRPG"        "SNRPD1"       "SNRPD3"       "RPL7A"       
[334] "RPS4X"        "ACTA2"        "RHOB"         "VSNL1"        "RPL30"        "RPL31"        "GNAI1"        "RPS21"        "RACK1"       
[343] "TPM4"         "EEF1A1"       "TUBA4A"       "PAFAH1B2"     "CXADR"        "CNTNAP1"      "PRKDC"        "NUCB2"        "BASP1"       
[352] "RPL24"        "PURA"         "FKBP3"        "DR1"          "TOP2B"        "ACY1"         "LMNB2"        "DNM1"         "EEF1A2"      
[361] "PSME1"        "CKAP4"        "KHDRBS1"      "PPP3CA"       "DHX9"         "MFGE8"        "SF3A3"        "ILF3"         "LMAN2"       
[370] "CBX3"         "SRSF9"        "PABPC4"       "OS9"          "TUBB3"        "CUL3"         "EIF3A"        "MVP"          "GOLGB1"      
[379] "SEPTIN2"      "PAFAH1B3"     "RAB35"        "TMED2"        "PCBP1"        "ELOC"         "SF3B3"        "SAFB"         "SHH"         
[388] "MAPRE2"       "HMGN3"        "EFNB3"        "SEPTIN7"      "ADRM1"        "INA"          "DDB1"         "ATP2B3"       "H2AC20"      
[397] "H2BC21"       "P3H1"         "LSM12"        "PREPL"        "XKR4"         "MIA3"         "FHL1"         "ATAT1"        "CEP170"      
[406] "ODR4"         "SF3B4"        "Q5T0I0"       "FKBP15"       "NBEA"         "SRSF11"       "LSM14B"       "HEXB"         "CD276"       
[415] "MRPL14"       "PRPF8"        "PLPPR3"       "NSMF"         "PPP1R21"      "TUBA1A"       "SND1"         "TRMT10C"      "DGLUCY"      
[424] "COMMD6"       "NECAB2"       "PRRT2"        "CENPV"        "PRUNE1"       "SETD3"        "NT5DC3"       "MB21D2"       "CCAR2"       
[433] "GPD1L"        "ARFGAP1"      "ARL10"        "GATD1"        "ATAD1"        "LEMD2"        "NUP43"        "CMAS"         "NPLOC4"      
[442] "PLPPR1"       "STT3B"        "BRSK1"        "HNRNPLL"      "SCG3"         "CTNNBL1"      "HTRA1"        "HDAC2"        "NEO1"        
[451] "KHSRP"        "MYDGF"        "ERGIC1"       "SLC25A46"     "PBXIP1"       "VPS33A"       "FKBP10"       "FAF2"         "NTNG2"       
[460] "DNAJC19"      "RBMXL1"       "DYNLL2"       "VMP1"         "MAP6"         "MBOAT7"       "VPS35"        "PURB"         "PANX1"       
[469] "RUFY1"        "PSMD1"        "PFDN5"        "NAP1L4"       "NIPSNAP1"     "PRXL2A"       "ERP44"        "FSD1"         "PAXX"        
[478] "DPCD"         "TPPP3"        "MRPL9"        "NLN"          "NSD3"         "API5"         "NAT10"        "COMMD4"       "NAPB"        
[487] "NUCKS1"       "RBSN"         "EHD4"         "TMX1"         "RPAP3"        "ACAD9"        "GORASP2"      "MRPL44"       "C17orf75"    
[496] "XPO5"         "GRPEL1"       "VAT1L"        "PLXNA4"       "LZTFL1"       "PLCB1"        "GPHN"         "FARSB"        "IARS2"       
[505] "ATAD3A"       "SLTM"         "CMTM6"        "P4HTM"        "CACNA2D2"     "SMPD3"        "PODXL2"       "STMN3"        "IGF2BP1"     
[514] "THYN1"        "NDUFAF4"      "NDUFA13"      "RAI14"        "MACROH2A2"    "TMEM63C"      "GNG12"        "HDAC6"        "MPZL1"       
[523] "SRP68"        "DPP7"         "NRBP1"        "ATP5IF1"      "CNOT7"        "FBXO2"        "CDV3"         "ASAP1"        "CADPS"       
[532] "PROCR"        "PHF24"        "DNM3"         "PA2G4"        "VDAC3"        "CNPY2"        "WDR37"        "EPB41L3"      "NOP58"       
[541] "LSM2"         "SF3B6"        "FIS1"         "RTCB"         "TLN1"         "DAAM1"        "ATP6V1D"      "TIMM13"       "GMPPB"       
[550] "COPG1"        "FKBP7"        "IGF2BP2"      "ERC1"        
# bright genome overlap
contrast_list <- c("IGSF9B-KO", "INPP5F-KO","IP6K2-KO","SH3GL2-KO") # Specify the contrasts of interest

result.dark <- get_gene_overlap_and_unique(filtered_DEP, contrast_list)

# Print results
print(result.dark$`Overlapping Genes`) # Genes common across all specified contrasts
 [1] "PCP4L1"  "SYNM"    "CSPG5"   "UTS2"    "TH"      "CSRP1"   "VAMP1"   "MAOB"    "NOVA1"   "GPM6A"   "DYNLT3"  "EPHB1"   "SNCB"    "CARTPT"  "PDK4"   
[16] "LBH"     "SV2A"    "FAM162A" "LSM14B"  "SLC6A17" "PSD3"    "NTM"     "SLC17A6" "GNG12"   "SUN2"    "PHF24"  
#print(result.dark$`Unique Genes`) # List of genes unique to each contrast

Look at overlap in contrasts that also have targeted pathways changes that match


print(result.THdown$`Overlapping Genes`) # Genes common across all specified contrasts
 [1] "EPHB1"    "PSD3"     "PYCR1"    "NCAM2"    "SLC16A3"  "RTN3"     "HP"       "FTL"      "HSPB1"    "TH"       "ALDOC"    "MAOA"     "MAOB"    
[14] "CALR"     "ACLY"     "CACNA2D1" "HADHB"    "RAP1B"    "VSNL1"    "ALCAM"    "COTL1"    "SV2A"     "CNDP2"    "SYT4"     "CACNA2D2" "NTM"     
[27] "RRBP1"    "FBXO2"   

plot_protein_heatmap_zscore(
  data = df,
  proteins = result.THdown$`Overlapping Genes`, # Example protein names
  sample_patterns = c("Control","PRKN.KO","IGSF9B" ,"SH3GL2.KO"),
  colors = c("snow", "lightgoldenrod1", "gold1", "darkorange1","red", "red2", "firebrick4"),
  scale_values = c(-1, -0.5,-0.25, 0, 1, 2.5, 4.5), # Adjust based on your data range
  group_means = TRUE,# Set to FALSE if you want individual samples
   tile_width = 0.25
) 
[1] "Sample columns selected: Control.1, Control.2, Control.3, Control.4, IGSF9B.KO.1, IGSF9B.KO.2, SH3GL2.KO.1, SH3GL2.KO.2, SH3GL2.KO.3"

Function to plot grouped by expression


# Example usage
heatmap_plot <- plot_clustered_protein_heatmap_zscore(
  data = df,
  proteins = result.THdown$`Overlapping Genes`, # Example protein names
  sample_patterns = c("Control", "IGSF9B.KO", "SH3GL2.KO"),
  colors = c("snow", "lightgoldenrod1", "gold1", "darkorange1", "red2", "firebrick4"),
  scale_values =c(-1, -0.5,-0.25, 0, 1, 2.5, 4.5), # Adjust based on your data range
  group_means = FALSE, # Set to FALSE if you want individual samples
  ) 
[1] "Sample columns selected: Control.1, Control.2, Control.3, Control.4, IGSF9B.KO.1, IGSF9B.KO.2, SH3GL2.KO.1, SH3GL2.KO.2, SH3GL2.KO.3"


# Example usage
heatmap_plot <- plot_clustered_protein_heatmap_zscore(
  data = df,
  proteins = result.THdown$`Overlapping Genes`, # Example protein names
  sample_patterns = c("Control", "IGSF9B.KO", "SH3GL2.KO"),
  colors = c("snow", "lightgoldenrod1", "gold1", "darkorange1", "red2", "firebrick4"),
  scale_values = c(-1, -0.5,-0.25, 0, 1, 2.5, 4.5), # Adjust based on your data range
  group_means = TRUE, # Set to FALSE if you want individual samples
  cell_width = 20, # Control column width
  cell_height = 10 # Control row height
)
[1] "Sample columns selected: Control.1, Control.2, Control.3, Control.4, IGSF9B.KO.1, IGSF9B.KO.2, SH3GL2.KO.1, SH3GL2.KO.2, SH3GL2.KO.3"

# Example usage
heatmap_plot <- plot_clustered_protein_heatmap_zscore(
  data = df,
  proteins = result.THdown$`Overlapping Genes`,  # Example protein names
  sample_patterns = c("Control", "IGSF9B.KO", "SH3GL2.KO"),
  colors = c("snow", "lightgoldenrod1", "gold1", "darkorange1", "red2", "firebrick4"),
  scale_values = c(-1, -0.5,-0.25, 0, 1, 2.5, 4.5), # Adjust based on your data range
  group_means = FALSE, # Set to FALSE if you want individual samples
  cell_width = 20, # Control column width
  cell_height = 10 # Control row height
)
[1] "Sample columns selected: Control.1, Control.2, Control.3, Control.4, IGSF9B.KO.1, IGSF9B.KO.2, SH3GL2.KO.1, SH3GL2.KO.2, SH3GL2.KO.3"

contrast_list <- c("PRKN-KO","IGSF9B-KO","SH3GL2-KO", "IP6K2-KO") # Specify the contrasts of interest

result.GCasedown <- get_gene_overlap_and_unique(filtered_DEP, contrast_list)

# Print results
print(result.GCasedown$`Overlapping Genes`) # Genes common across all specified contrasts
[1] "EPHB1"    "PSD3"     "TH"       "MAOB"     "CACNA2D1" "SV2A"     "NTM"     

Overlapping list of the genotypes with GCAse activity down: GBA-KO, PRNK-KO, INPP5F-KO, SH3GL2-KO, IP6K2-KO


# Example usage
heatmap_plot <- plot_clustered_protein_heatmap_zscore(
  data = df,
  proteins = result.GCasedown$`Overlapping Genes`,  # Example protein names
  sample_patterns = c("Control", "IGSF9B.KO", "SH3GL2.KO","IP6K2.KO"),
  colors = c("snow", "lightgoldenrod1", "gold1", "darkorange1", "red2", "firebrick4"),
  scale_values = c(-1.5, -1,-0.5, 0, 1, 2, 2.5), # Adjust based on your data range
  group_means = FALSE, # Set to FALSE if you want individual samples
  cell_width = 20, # Control column width
  cell_height = 10 # Control row height
)
[1] "Sample columns selected: Control.1, Control.2, Control.3, Control.4, IGSF9B.KO.1, IGSF9B.KO.2, IP6K2.KO.1, IP6K2.KO.2, IP6K2.KO.4, SH3GL2.KO.1, SH3GL2.KO.2, SH3GL2.KO.3"


pro.list <- result.lyso$`Overlapping Genes`

# Example usage
heatmap_plot <- plot_clustered_protein_heatmap_zscore(
  data = df,
  proteins = pro.list, # Example protein names
  sample_patterns = c("Control", "IGSF9B.KO", "SH3GL2.KO","IP6K2.KO"),
  colors = c("snow", "lightgoldenrod1", "gold1", "darkorange1", "red2", "firebrick4"),
  scale_values = c(-0.5,-0.25, 0, 2.5, 4.5, 6.5), # Adjust based on your data range
  group_means = TRUE, # Set to FALSE if you want individual samples
  cell_width = 20, # Control column width
  cell_height = 10 # Control row height
)
[1] "Sample columns selected: Control.1, Control.2, Control.3, Control.4, IGSF9B.KO.1, IGSF9B.KO.2, IP6K2.KO.1, IP6K2.KO.2, IP6K2.KO.4, SH3GL2.KO.1, SH3GL2.KO.2, SH3GL2.KO.3"

# Example usage
heatmap_plot <- plot_clustered_protein_heatmap_zscore(
  data = df,
  proteins = pro.list,  # Example protein names
  sample_patterns = c("Control", "IGSF9B.KO", "SH3GL2.KO","IP6K2.KO"),
  colors = c("snow", "lightgoldenrod1", "gold1", "darkorange1", "red2", "firebrick4"),
  scale_values = c(-0.5,-0.25, 0, 2.5, 4.5, 6.5), # Adjust based on your data range
  group_means = FALSE, # Set to FALSE if you want individual samples
  cell_width = 20, # Control column width
  cell_height = 10 # Control row height
)
[1] "Sample columns selected: Control.1, Control.2, Control.3, Control.4, IGSF9B.KO.1, IGSF9B.KO.2, IP6K2.KO.1, IP6K2.KO.2, IP6K2.KO.4, SH3GL2.KO.1, SH3GL2.KO.2, SH3GL2.KO.3"

lysome <- read_excel("/Users/rhalenathomas/Downloads/Move_Data/DarkGenomeResult/List of genes for RNAseq or Proteomics/LYSOSOME_GENE LIST.xlsx")

Gene list



plot_protein_heatmap_zscore(
  data = df,
  proteins = lysome$`Gene name`, # Example protein names
  sample_patterns = c("Control","INPP5F.KO","SH3GL2.KO"),
  colors = c("snow", "lightgoldenrod1", "gold1", "darkorange1","red", "red2", "firebrick4"),
  scale_values = c(-1, -0.5,-0.25, 0, 1, 2.5, 5.5), # Adjust based on your data range
  group_means = TRUE,# Set to FALSE if you want individual samples
   tile_width = 0.25
) 
[1] "Sample columns selected: Control.1, Control.2, Control.3, Control.4, INPP5F.KO.1, INPP5F.KO.2, INPP5F.KO.3, SH3GL2.KO.1, SH3GL2.KO.2, SH3GL2.KO.3"

get overlap lists

colnames(df)
 [1] "Symbol"      "Control.1"   "Control.2"   "Control.3"   "Control.4"   "IGSF9B.KO.1" "IGSF9B.KO.2" "INPP5F.KO.1" "INPP5F.KO.2" "INPP5F.KO.3"
[11] "IP6K2.KO.1"  "IP6K2.KO.2"  "IP6K2.KO.4"  "SH3GL2.KO.1" "SH3GL2.KO.2" "SH3GL2.KO.3"

contrast_list <- c("INPP5F-KO","SH3GL2-KO","IP6K2-KO","IGSF9B-KO") # Specify the contrasts of interest
dark.ol <- get_gene_overlap_and_unique(filtered_DEP, contrast_list)

print(dark.ol)
$`Overlapping Genes`
 [1] "PCP4L1"  "SYNM"    "CSPG5"   "UTS2"    "TH"      "CSRP1"   "VAMP1"   "MAOB"    "NOVA1"   "GPM6A"   "DYNLT3"  "EPHB1"   "SNCB"    "CARTPT"  "PDK4"   
[16] "LBH"     "SV2A"    "FAM162A" "LSM14B"  "SLC6A17" "PSD3"    "NTM"     "SLC17A6" "GNG12"   "SUN2"    "PHF24"  

$`Unique Genes`
$`Unique Genes`$`INPP5F-KO`
 [1] "PIGBOS1" "CLIC1"   "STX16"   "U2SURP"  "NACAD"   "XPOT"    "STX6"    "SIN3B"   "DAB1"    "TUSC2"   "ACTL6B"  "ZRANB2"  "BAG3"    "CFB"     "ASS1"   
[16] "P01861"  "APOH"    "ALB"     "TF"      "HPX"     "FUCA1"   "S100B"   "SNRNP70" "SLC2A1"  "SCG2"    "UBTF"    "POLR2E"  "PPIB"    "AK4"     "CRABP1" 
[31] "ERP29"   "GCHFR"   "SHMT2"   "GARS1"   "NSG1"    "SLC1A4"  "SMS"     "SUB1"    "MANF"    "TRA2B"   "NUCB2"   "SRSF3"   "SRSF2"   "PPARD"   "CD47"   
[46] "FLII"    "SRSF9"   "SRSF6"   "SQSTM1"  "PRP4K"   "IDI1"    "SAFB2"   "SMC1A"   "CHD4"    "RNPS1"   "TERF2"   "PTPRN"   "MAP7D1"  "HP1BP3"  "UBR4"   
[61] "ARFGEF3" "CD276"   "ARSK"    "ARMCX2"  "NDUFAF7" "MICALL1" "PRUNE2"  "COPS9"   "KCTD12"  "RBM17"   "PPP1R9B" "CNN2"    "SF3B5"   "C1QTNF4" "SPRY4"  
[76] "PNN"     "GHITM"   "EHMT1"   "GMPR2"   "TAGLN3" 

$`Unique Genes`$`SH3GL2-KO`
 [1] "AIP"      "GTPBP1"   "MGRN1"    "LY6H"     "CNTN5"    "KBTBD11"  "SLC25A4"  "POLR2C"   "ATP2B1"   "GLRX"     "ALDH9A1"  "ALDH7A1"  "BCAM"    
[14] "HSD17B4"  "KPNA1"    "TPD52"    "NCALD"    "PAFAH1B2" "GPM6B"    "GRM7"     "ETFDH"    "FRY"      "TBC1D9B"  "ZC3HAV1"  "ARHGAP12" "GDPD1"   
[27] "NUDT10"   "ITFG1"    "MICAL1"   "MYDGF"    "SH3KBP1"  "CHAMP1"   "LYSMD1"   "TSPAN18"  "HSD17B10" "OLFM1"    "DNAJC5"   "HEBP1"    "ABCB8"   
[40] "TMEM30A"  "GDE1"     "GPRC5B"   "EHD3"     "CACFD1"   "SEPTIN9"  "GRID1"    "NFU1"     "GAB2"     "COPG1"   

$`Unique Genes`$`IP6K2-KO`
 [1] "PDLIM1"  "EDIL3"   "BRD4"    "WDR1"    "PRKCB"   "NEFH"    "PRKCA"   "PLCG1"   "ITGA6"   "NF2"     "FDFT1"   "MTIF2"   "DLG4"    "EPS8"    "RAPGEF1"
[16] "CIRBP"   "FKBP8"   "CYP51A1" "PRPF40B" "SUGP2"   "SCAI"    "SYNE1"   "PLPPR1"  "FBXO41"  "SPOCK2"  "EVI5L"   "FMNL2"   "FYTTD1"  "CAMK2N2" "SRCIN1" 
[31] "NT5DC2"  "SERINC1" "RPRM"    "TES"     "OGDHL"   "TDRKH"   "TMX2"   

$`Unique Genes`$`IGSF9B-KO`
   [1] "ESYT2"               "SHTN1"               "ILVBL"               "DENND3"              "PALM3"               "CASTOR2"            
   [7] "FAM171A2"            "MCRIP1"              "SLC35A4"             "DNASE2"              "KIF2A"               "ACOT7"              
  [13] "MYO1C"               "DFFA"                "RTCA"                "MANBA"               "SDCBP"               "RNASET2"            
  [19] "PODXL"               "MAN2B1"              "PDXK"                "ARID1A"              "SDHD"                "DPYSL4"             
  [25] "COX7A2L"             "UBFD1"               "ABLIM1"              "ADAM10"              "EI24"                "TP53I11"            
  [31] "PDCD5"               "TPP1"                "CPLX1"               "PSMA7"               "LIN7A"               "TIMM23"             
  [37] "CASK"                "UQCRQ"               "CLGN"                "SYN3"                "SPTBN2"              "KIF3B"              
  [43] "DCLK1"               "SNPH"                "DEGS1"               "SCAMP2"              "PGRMC2"              "PFDN6"              
  [49] "RER1"                "SURF4"               "SPTLC1"              "HMGB3"               "STX7"                "YKT6"               
  [55] "FABP7"               "RNMT"                "SEPTIN4"             "DYNC1LI2"            "SRGAP3"              "TXNL1"              
  [61] "TPD52L2"             "SYNJ1"               "PROM1"               "TGOLN2"              "DENR"                "DCX"                
  [67] "NCK2"                "TSPAN6"              "ZNF207"              "NDUFB5"              "NDUFB3"              "AP1G1"              
  [73] "SGTA"                "SLC25A20"            "NUDT21"              "CALU"                "EXTL3"               "MFSD11"             
  [79] "SPAG9"               "KIF5C"               "ACSL4"               "SYNCRIP"             "SELENOF"             "TSPAN2"             
  [85] "TSPAN3"              "SNAP91"              "DPM1"                "TIMM17B"             "PRAF2"               "CUTA"               
  [91] "PFDN1"               "ABCB7"               "SRGAP2"              "DNAJC6"              "ATP9A"               "CLASP2"             
  [97] "PPFIA3"              "TBCA"                "MPDU1"               "MACROH2A1"           "PEX14"               "NDUFB1"             
 [103] "ERLIN1"              "CLN5"                "HSBP1"               "BANF1"               "TIPRL"               "PPM1B"              
 [109] "ADAP1"               "PALM"                "ATP6AP2"             "EIF3G"               "EIF3J"               "ZMPSTE24"           
 [115] "IDH1"                "ATRN"                "DGAT1"               "PAK3"                "ARL6IP5"             "FLOT1"              
 [121] "TRIO"                "ATP5MG"              "GLRX3"               "RSL1D1"              "SNCG"                "DDAH1"              
 [127] "B3GAT3"              "DDHD2"               "NFASC"               "TMCC1"               "ERLIN2"              "ENDOD1"             
 [133] "GLS"                 "WDR47"               "AP2A2"               "CLSTN1"              "YIF1A"               "NDUFB4"             
 [139] "SBF1"                "VAPB"                "SNAPIN"              "NDUFC2"              "FKBP9"               "PGLS"               
 [145] "SEC24A"              "OXSR1"               "GGPS1"               "BAG2"                "DDAH2"               "TXNDC12"            
 [151] "NDUFB10"             "TOMM40"              "PEX11B"              "COX2"                "HPRT1"               "AK1"                
 [157] "ATP6"                "HRAS"                "IGF2"                "LMNA"                "APOE"                "APOC3"              
 [163] "TFRC"                "FTH1"                "GBA1"                "ALDOA"               "CSTB"                "OAT"                
 [169] "TUBB4A"              "HLA-A"               "RPN1"                "RPN2"                "PCCA"                "PCCB"               
 [175] "SCG5"                "ATP5MC1"             "ITGB1"               "GLA"                 "PTMA"                "GPI"                
 [181] "TPM3"                "HEXA"                "EPHX1"               "LDHB"                "NEFL"                "NEFM"               
 [187] "P4HB"                "H1-0"                "ACYP1"               "CTSD"                "ANXA2"               "TUBB"               
 [193] "PSAP"                "HEXB"                "CTSB"                "LAMB1"               "ANXA6"               "SYP"                
 [199] "ANXA5"               "SNRPA"               "ENO2"                "GNAO1"               "CLTA"                "ANXA4"              
 [205] "COX6C"               "UCHL1"               "SMIM13"              "RAP2A"               "GAA"                 "H1-4"               
 [211] "TXN"                 "CTSA"                "MAPT"                "CHGA"                "HSPD1"               "CLU"                
 [217] "HSPA5"               "ACP2"                "MAP2"                "PDHB"                "DBT"                 "RALA"               
 [223] "RALB"                "LAMP1"               "TOP2A"               "G6PD"                "UBL4A"               "IGF2R"              
 [229] "PCNA"                "COL6A1"              "CKMT1B"              "CKMT1A"              "ACTN1"               "PEPD"               
 [235] "LAMP2"               "NCAM1"               "ATP1A3"              "P4HA1"               "PRKAR2A"             "MIF"                
 [241] "FDPS"                "COX7A2"              "PKM"                 "HNRNPL"              "UQCRB"               "AKR1B1"             
 [247] "ARSA"                "UCHL3"               "CD46"                "GNS"                 "ARSB"                "RPA2"               
 [253] "COX7C"               "GLB1"                "PPP3CB"              "H1-5"                "H1-3"                "H1-2"               
 [259] "CPE"                 "STMN1"               "NAGA"                "GOT1"                "NDUFB7"              "SYN1"               
 [265] "DES"                 "GAP43"               "GM2A"                "SON"                 "GNAZ"                "ANXA7"              
 [271] "RAB3B"               "PTMS"                "GSTM3"               "ATP6V1B2"            "ATP6V1C1"            "CNR1"               
 [277] "SYT1"                "VDAC1"               "OSBP"                "PCMT1"               "FBL"                 "FDXR"               
 [283] "PRKACB"              "UQCRC2"              "GCSH"                "PTPRD"               "CFL1"                "EEF1B2"             
 [289] "TNC"                 "GRK2"                "PSMA1"               "PSMA3"               "PSMA4"               "DDX6"               
 [295] "CNTFR"               "YWHAQ"               "MARK3"               "MAP4"                "CANX"                "PSMA5"              
 [301] "PSMB6"               "PSMB5"               "TMOD1"               "GRN"                 "LAP3"                "IMPA1"              
 [307] "EPHB2"               "CMPK1"               "PEBP1"               "CORO1A"              "GDI1"                "PRKAR2B"            
 [313] "TIA1"                "UQCRC1"              "YWHAB"               "STIP1"               "S100A11"             "L1CAM"              
 [319] "PRDX2"               "GALNS"               "SDC2"                "HSPA4"               "PFN2"                "CTNNA1"             
 [325] "PHB1"                "MYH9"                "MYH10"               "ADD1"                "ADD2"                "BSG"                
 [331] "PPM1A"               "HMGCL"               "P36268"              "ARL3"                "DLST"                "GPX4"               
 [337] "NUP62"               "SNCA"                "LIPA"                "ATP6V1A"             "COL18A1"             "MDH1"               
 [343] "HADHA"               "CETN2"               "CD200"               "ACTR1B"              "EPS15"               "CASP3"              
 [349] "ACAA2"               "RPL35"               "PRCP"                "ECE1"                "PAFAH1B1"            "SSR1"               
 [355] "VDAC2"               "CRK"                 "CRKL"                "NSF"                 "MAP1B"               "STT3A"              
 [361] "RAP1GAP"             "CAPZB"               "UQCRFS1"             "TFPI2"               "PIP4K2A"             "PPP3CC"             
 [367] "CD151"               "NES"                 "HSPA13"              "MARCKSL1"            "LMAN1"               "AMPH"               
 [373] "INPP1"               "HARS2"               "PSMB3"               "ACADVL"              "TMED10"              "PSEN1"              
 [379] "TSC2"                "GSK3B"               "NT5C2"               "SEPHS1"              "GDI2"                "CPT1A"              
 [385] "SERPINB9"            "ST13"                "ANXA11"              "SSR4"                "HCFC1"               "ALDH5A1"            
 [391] "PSMD7"               "HDGF"                "PGD"                 "RAP1GDS1"            "GTF2A1"              "KIF11"              
 [397] "HMGA2"               "PPP5C"               "MVD"                 "CTSC"                "PTTG1IP"             "SLC16A1"            
 [403] "RAD23A"              "RAD23B"              "ALDH18A1"            "MFAP2"               "AFDN"                "CDH6"               
 [409] "HNRNPH2"             "BID"                 "ARPP19"              "AP1S2"               "CORO7"               "EPPK1"              
 [415] "FXYD7"               "TPI1"                "SEC61B"              "PSMA6"               "S100A10"             "SPCS3"              
 [421] "UBE2K"               "UBE2N"               "RPL26"               "STX1B"               "RPL27"               "PCBD1"              
 [427] "SEC61A1"             "VBP1"                "STXBP1"              "DAD1"                "NPC2"                "PKIA"               
 [433] "SUMO2"               "UFM1"                "AP1S1"               "YWHAG"               "YWHAE"               "RPS18"              
 [439] "RPS13"               "ARF6"                "PPP2CB"              "RHOB"                "RPS6"                "RPS24"              
 [445] "GNB1"                "RBX1"                "RPL32"               "PPIA"                "FKBP1A"              "RAC1"               
 [451] "VAMP2"               "YWHAZ"               "PPP2CA"              "YBX1"                "SEC11A"              "UBE2L3"             
 [457] "TUBA4A"              "TUBB4B"              "CXADR"               "GTF2I"               "PIP4K2B"             "SLC35A1"            
 [463] "ARG2"                "BASP1"               "MRPS11"              "ARF5"                "H3-3A"               "H3-3B"              
 [469] "HSPG2"               "CYCS"                "SLC25A3"             "CDK5"                "CLTC"                "TIAL1"              
 [475] "SET"                 "AMPD2"               "CTBS"                "CAP1"                "HMGCS1"              "DR1"                
 [481] "ATP2B2"              "EWSR1"               "OCRL"                "PLOD1"               "RPL6"                "SLC25A11"           
 [487] "PTS"                 "MVK"                 "EEF1A2"              "PSME1"               "PRDX1"               "CKAP4"              
 [493] "TJP1"                "KLC1"                "LRP1"                "ARHGAP1"             "PPP3CA"              "GOLGA3"             
 [499] "LGALS3BP"            "MFGE8"               "DMTN"                "PPID"                "SCRN3"               "GALNT2"             
 [505] "AP1B1"               "KIF1A"               "SCRN1"               "CNTN1"               "LMAN2"               "ANK3"               
 [511] "PAK1"                "PAK2"                "DNAJC3"              "NME3"                "MAD2L1"              "PTK7"               
 [517] "AP3B2"               "UBE2V1"              "PEDS1-UBE2V1"        "DYNC1I2"             "OS9"                 "PDAP1"              
 [523] "TMED1"               "LSAMP"               "MTX1"                "TUBB3"               "CAMK2B"              "DCTN2"              
 [529] "STIM1"               "ITGA7"               "MOGS"                "SPTAN1"              "TUBB2A"              "HNRNPD"             
 [535] "SCARB2"              "DAG1"                "MLEC"                "TTLL12"              "MPP2"                "CRMP1"              
 [541] "DPYSL3"              "DCTN1"               "EIF4A2"              "FLOT2"               "FLNC"                "ELAVL3"             
 [547] "INPP5A"              "CLINT1"              "GANAB"               "LBR"                 "MVP"                 "SPCS2"              
 [553] "EMC2"                "PSMD6"               "SEPTIN2"             "RRS1"                "POSTN"               "PDIA6"              
 [559] "PAFAH1B3"            "PPP2R5B"             "PTPA"                "QPRT"                "RABEP1"              "RCN1"               
 [565] "TMED2"               "SHH"                 "MAPRE2"              "SF1"                 "MAPRE1"              "EFNB3"              
 [571] "RAB30"               "ITSN1"               "TBCE"                "UBE2V2"              "VAMP3"               "NEDD8"              
 [577] "INA"                 "CSRP2"               "DPYSL2"              "STX1A"               "CPSF6"               "SMN2"               
 [583] "SMN1"                "DBN1"                "FSCN1"               "ATP2B3"              "TST"                 "HAGH"               
 [589] "H2BC21"              "PTPRO"               "UGP2"                "HNRNPUL2"            "P3H1"                "LSM12"              
 [595] "CCDC88A"             "LGALSL"              "VPS26B"              "CCDC184"             "TMEM35A"             "HSD17B12"           
 [601] "RAB6D"               "SDK2"                "TMEM97"              "YIF1B"               "MEST"                "XKR4"               
 [607] "NOMO2"               "MIA3"                "WDR44"               "GNAS"                "SAMD4B"              "ATAT1"              
 [613] "CEP170"              "CLVS2"               "TPRG1L"              "FNBP1L"              "GPR158"              "WLS"                
 [619] "Q5TF21"              "MICOS10"             "WASHC2A"             "PPP2R2D"             "MBLAC2"              "LMBRD2"             
 [625] "IQSEC1"              "CARMIL2"             "RALGAPA1"            "TMEM132E"            "TCEAL6"              "SLC25A24"           
 [631] "REEP3"               "ARMC6"               "JMJD6"               "PPP1R18"             "SLC48A1"             "SLC27A4"            
 [637] "EDC4"                "SCYL2"               "CNNM4"               "ERICH5"              "MEAK7"               "PGM2L1"             
 [643] "AAGAB"               "TMEM65"              "NCEH1"               "CPLX2"               "MOXD1"               "CYP20A1"            
 [649] "POGLUT2"             "TMEM205"             "ISLR2"               "APOOL"               "PACS1"               "RAB11FIP1"          
 [655] "HSDL2"               "CRACD"               "GPRIN3"              "TOM1L2"              "TMTC3"               "IKBIP"              
 [661] "UBE2R2"              "TLCD3B"              "TUBA1A"              "RUFY3"               "EPM2AIP1"            "TAOK1"              
 [667] "MOB1B"               "CHMP1B"              "MICAL3"              "GPRIN1"              "NUP54"               "KIF21A"             
 [673] "PRRT2"               "TMED4"               "GALNT7"              "PRUNE1"              "MAGI2"               "USP48"              
 [679] "NT5DC3"              "CAND1"               "OSTM1"               "DDX42"               "NDUFA11"             "DOLPP1"             
 [685] "GPSM1"               "ERC1"                "NUDCD3"              "SLC44A2"             "BRSK2"               "SULF2"              
 [691] "DNAJC10"             "RHOT2"               "SIRT2"               "NRM"                 "SMAP1"               "KIAA0319L"          
 [697] "CACNA2D3"            "CEND1"               "NUP93"               "ABHD12"              "SLC43A2"             "CADM2"              
 [703] "MMGT1"               "AFAP1"               "CALHM5"              "KCNRG"               "JAGN1"               "COMMD1"             
 [709] "EMC1"                "AMER2"               "GATD1"               "GOLM1"               "COLGALT1"            "SUMF2"              
 [715] "TMEM87A"             "TXNDC5"              "LEMD2"               "NECAP1"              "CAMKV"               "PLA2G15"            
 [721] "Q8NCU8"              "MROH1"               "EHBP1"               "MCU"                 "NUP37"               "NBEA"               
 [727] "NLGN2"               "CADM4"               "PLBD2"               "GRPEL2"              "FGFBP3"              "UBA3"               
 [733] "C18orf32"            "STT3B"               "HM13"                "GPX8"                "RAPGEF6"             "C16orf78"           
 [739] "PDCD6IP"             "PSPC1"               "PPM1E"               "JDP2"                "LZIC"                "IRGQ"               
 [745] "DDX1"                "H1-10"               "NCSTN"               "TM9SF4"              "WASF1"               "SLC9A6"             
 [751] "NDRG1"               "NUP205"              "TTC9"                "SORL1"               "ARPC1A"              "GGH"                
 [757] "NRCAM"               "KIFAP3"              "CELF1"               "GLG1"                "PTPRN2"              "KHSRP"              
 [763] "USP9X"               "STMN2"               "BORCS5"              "UBE2E3"              "NCLN"                "ERGIC1"             
 [769] "CCDC47"              "TMEM230"             "FUBP1"               "VTI1A"               "MCUR1"               "FKBP10"             
 [775] "TOMM6"               "ARL8A"               "CCDC127"             "EFHD2"               "PYCR2"               "DCPS"               
 [781] "PPP1R14B"            "ISOC1"               "FOXRED1"             "AP2M1"               "RAB39B"              "CMBL"               
 [787] "ERLEC1"              "RAB3C"               "DAZAP1"              "SGTB"                "CYFIP2"              "CNRIP1"             
 [793] "LINGO1"              "DYNLL2"              "OTUB1"               "CHMP6"               "CERS2"               "ZC2HC1A"            
 [799] "CRELD1"              "SFRP2"               "DIRAS2"              "CDK5RAP3"            "TMX3"                "FAM210B"            
 [805] "PHACTR3"             "PRRC1"               "GDAP1L1"             "VSTM2L"              "MBOAT7"              "RUNDC3B"            
 [811] "NAP1L5"              "AGAP3"               "MIA2"                "NEDD4L"              "VPS35"               "MAGI1"              
 [817] "PANX1"               "PIGS"                "SLC9A7"              "YME1L1"              "SCN2A"               "TBCB"               
 [823] "SEC62"               "PFDN5"               "PARK7"               "TSC22D3"             "TTC1"                "PHB2"               
 [829] "ATXN2"               "SEPTIN5"             "SIGMAR1"             "NAPG"                "EBNA1BP2"            "H2BC13"             
 [835] "DPYSL5"              "ECSIT"               "SYT3"                "TXNDC17"             "NUDT16L1"            "SDF4"               
 [841] "ERP44"               "ESYT1"               "TMEM43"              "FSD1"                "FUCA2"               "LMF2"               
 [847] "TUBB2B"              "TMEM109"             "PBDC1"               "PTDSS2"              "TMED9"               "TPPP3"              
 [853] "ACAT2"               "CHID1"               "FSD1L"               "AP1M1"               "RAB34"               "TRIM2"              
 [859] "SEMA4C"              "TTYH3"               "YIPF3"               "NDEL1"               "ROGDI"               "PITHD1"             
 [865] "MAP1LC3B"            "UBA5"                "NAT10"               "KLC2"                "FXYD6"               "HDHD2"              
 [871] "MAGT1"               "LMAN2L"              "NAPB"                "SIL1"                "NUCKS1"              "SH3BGRL3"           
 [877] "SLC38A1"             "CPVL"                "DPAGT1"              "POFUT1"              "PIGU"                "MAP1LC3A"           
 [883] "CLSTN2"              "EPB41L1"             "SMDT1"               "PRR36"               "REEP1"               "SFXN1"              
 [889] "COG4"                "NMNAT1"              "C17orf75"            "TMEM165"             "GLOD4"               "PCDH9"              
 [895] "MCCC2"               "TM9SF3"              "APMAP"               "VTA1"                "NPHS2"               "DYNLRB1"            
 [901] "EMC7"                "PLCB1"               "PFDN4"               "EIF2B3"              "OSTC"                "RAB6B"              
 [907] "TOMM22"              "LRRC4B"              "RBM12"               "STAU2"               "SHFL"                "TMEM106B"           
 [913] "AGPAT5"              "CYRIB"               "EXOC1"               "TMEM38B"             "ANO10"               "NDUFB11"            
 [919] "OCIAD1"              "CHCHD3"              "P4HTM"               "BABAM2"              "DPP3"                "SCN3A"              
 [925] "SCN3B"               "TERF2IP"             "TMOD3"               "UGGT1"               "ERAP1"               "PODXL2"             
 [931] "TMOD2"               "CHMP5"               "HACD3"               "KCMF1"               "RAI14"               "MACROH2A2"          
 [937] "TBC1D7"              "TBC1D7-LOC100130357" "TOMM7"               "TMEM63C"             "CAMSAP3"             "NRXN2"              
 [943] "DPM3"                "NCDN"                "EPS15L1"             "MRC2"                "CPNE7"               "EXTL2"              
 [949] "DNAJB11"             "SEL1L"               "PEF1"                "ZMYM2"               "SLC25A10"            "CLIP2"              
 [955] "CFDP1"               "SEC63"               "SEPTIN3"             "CHORDC1"             "UBQLN2"              "PCYOX1"             
 [961] "PFDN2"               "PUF60"               "NRBP1"               "PLXNA1"              "GGT7"                "NAGK"               
 [967] "SH3BGRL2"            "SLC25A13"            "DBNL"                "PURG"                "GGA1"                "STOML2"             
 [973] "JPT1"                "PTBP2"               "TNIK"                "PITPNC1"             "MAN1B1"              "CDV3"               
 [979] "NRXN1"               "SLC39A10"            "ASAP1"               "CORO1C"              "HPCAL4"              "MYO6"               
 [985] "UBQLN1"              "SNX12"               "SYNRG"               "SSR3"                "FAF1"                "MINPP1"             
 [991] "NOVA2"               "NSFL1C"              "MAPK8IP3"            "USP24"               "AGTPBP1"             "MAPRE3"             
 [997] "CORO2B"              "DNM3"                "NUDC"                "CFL2"               
 [ reached getOption("max.print") -- omitted 35 entries ]

specify group function to get the specific overlap list in the upset plot

print(overlap_genes)
 [1] "EHD1"     "B4DLN1"   "CALD1"    "ATP6V0D1" "APRT"     "ATXN2L"   "CS"       "PSIP1"    "NDUFS3"   "TOMM70"   "GOT2"     "HMGN2"    "FH"      
[14] "VIM"      "ATP5PF"   "HK1"      "ATP5PB"   "ALDH1B1"  "GK"       "CBX5"     "FSTL1"    "PLEC"     "HMGB1"    "NXN"      "FAHD1"    "SERBP1"  
[27] "NUBPL"    "FUBP3"    "JPT2"     "SLC25A22" "PHPT1"    "SEPTIN10" "UBA2"     "ADD3"     "NENF"     "SUPT16H" 
length(overlap_genes)
[1] 36
write.csv(overlap_genes,"/Users/rhalenathomas/Downloads/Move_Data/DarkGenomeResult/omics/OverlapLGeneLists/GBA_PINK1_PRKN_DPE.csv")

Make list corresponding to the upset plot to save and send to Roxanne


# pink parkin
contrast_list <- c("PINK1-KO", "PRKN-KO")
overlap_genes <- get_specific_gene_overlap(filtered_DEP, contrast_list)
# Print the result
print("Overlap of PINK1 PRKN")
[1] "Overlap of PINK1 PRKN"
print(overlap_genes)
  [1] "PABPC1"     "RDX"        "MEA1"       "A0A5F9UP49" "ACAT1"      "SCRIB"      "CAST"       "EIF3E"      "ADAM9"      "EIF4H"      "PITRM1"    
 [12] "SRP54"      "ACSL3"      "LRPPRC"     "A2A2V1"     "NUDT5"      "TP53BP1"    "SUMO3"      "MATR3"      "EIF3H"      "MSI2"       "NQO1"      
 [23] "EIF3CL"     "SH3GLB2"    "CROT"       "CTNND1"     "MRPS27"     "EIF4B"      "EIF4G1"     "AGK"        "OGDH"       "EPB41L2"    "SLC3A2"    
 [34] "PCBP2"      "NDUFV1"     "H0Y3P2"     "COPB2"      "NACA"       "H3BN98"     "TBL3"       "KDSR"       "IGF2BP3"    "PIR"        "DHX15"     
 [45] "NDUFS4"     "PSMD3"      "TIMM44"     "BUB3"       "OPA1"       "USO1"       "EIF5B"      "NDUFS2"     "SH3BGRL"    "KHDRBS3"    "NTN1"      
 [56] "GSR"        "PARP1"      "LTA4H"      "RO60"       "XRCC5"      "CBR1"       "ATP2A2"     "CD36"       "SDHB"       "RPS12"      "ATP5F1A"   
 [67] "RPL13"      "EEF1G"      "TKT"        "PRDX5"      "DNAJA1"     "RPL9"       "ATP5F1C"    "SRP14"      "TALDO1"     "RPL3"       "MDH2"      
 [78] "CRAT"       "IQGAP1"     "ARCN1"      "GMPS"       "BCAP31"     "CLCN7"      "MRPL12"     "PSMD4"      "OXCT1"      "H2BC5"      "CD81"      
 [89] "TPM4"       "PRKDC"      "PURA"       "PABPC4"     "EIF3A"      "PCBP1"      "ELOC"       "SAFB"       "HMGN3"      "ADRM1"      "DDB1"      
[100] "PREPL"      "ODR4"       "FKBP15"     "SRSF11"     "NSMF"       "TRMT10C"    "COMMD6"     "SETD3"      "ARL10"      "ATAD1"      "NPLOC4"    
[111] "SCG3"       "NEO1"       "VPS33A"     "NTNG2"      "DNAJC19"    "PURB"       "RUFY1"      "PSMD1"      "NAP1L4"     "NIPSNAP1"   "PRXL2A"    
[122] "PAXX"       "DPCD"       "NLN"        "NSD3"       "COMMD4"     "RBSN"       "TMX1"       "ACAD9"      "GORASP2"    "MRPL44"     "XPO5"      
[133] "GRPEL1"     "LZTFL1"     "IARS2"      "ATAD3A"     "IGF2BP1"    "THYN1"      "NDUFAF4"    "NDUFA13"    "MPZL1"      "SRP68"      "CNOT7"     
[144] "PA2G4"      "VDAC3"      "CNPY2"      "NOP58"      "FIS1"       "TIMM13"     "IGF2BP2"   
length(overlap_genes)
[1] 150
write.csv(overlap_genes,"/Users/rhalenathomas/Downloads/Move_Data/DarkGenomeResult/omics/OverlapLGeneLists/PINK1_PRKN_DPE.csv")
print("saved")
[1] "saved"
# PRKN IGSF9B
contrast_list <- c("IGSF9B-KO", "PRKN-KO")
overlap_genes <- get_specific_gene_overlap(filtered_DEP, contrast_list)
# Print the result
print("Overlap of IGSF9B PRKN")
[1] "Overlap of IGSF9B PRKN"
print(overlap_genes)
 [1] "RTCA"     "PDXK"     "CASK"     "SYN3"     "SURF4"    "DENR"     "ACSL4"    "ZMPSTE24" "ATP5MG"   "DDAH1"    "ERLIN2"   "SEC24A"   "DDAH2"   
[14] "AK1"      "ALDOA"    "PCCA"     "TUBB"     "HSPD1"    "PDHB"     "ACTN1"    "PEPD"     "FDPS"     "UQCRB"    "CPE"      "CNR1"     "PCMT1"   
[27] "PRKACB"   "UQCRC2"   "PSMA4"    "PSMA5"    "PSMB6"    "CMPK1"    "PEBP1"    "PRDX2"    "PHB1"     "ADD2"     "ARL3"     "VDAC2"    "CRK"     
[40] "CRKL"     "UQCRFS1"  "PSMB3"    "GDI2"     "PGD"      "PPP5C"    "CDH6"     "PSMA6"    "SPCS3"    "UBE2K"    "VBP1"     "PPP2CB"   "FKBP1A"  
[53] "YBX1"     "AMPD2"    "MVK"      "PRDX1"    "LRP1"     "AP1B1"    "PAK2"     "PTK7"     "EIF4A2"   "GANAB"    "PTPA"     "RABEP1"   "NEDD8"   
[66] "DBN1"     "FSCN1"    "TMEM35A"  "SLC25A24" "CACNA2D3" "AFAP1"    "GRPEL2"   "IRGQ"     "ARPC1A"   "AP2M1"    "PARK7"    "CHID1"    "FSD1L"   
[79] "TTYH3"    "FXYD6"    "CPVL"     "ANO10"    "CHCHD3"   "TMOD2"    "EPS15L1"  "DBNL"     "STOML2"   "PTBP2"    "SLC39A10" "CFL2"    
length(overlap_genes)
[1] 90
write.csv(overlap_genes,"/Users/rhalenathomas/Downloads/Move_Data/DarkGenomeResult/omics/OverlapLGeneLists/IGSF9B_PRKN_DPE.csv")
print("saved")
[1] "saved"
# IGSF9B pink parkin
contrast_list <- c("PINK1-KO", "PRKN-KO", "IGSF9B-KO")
overlap_genes <- get_specific_gene_overlap(filtered_DEP, contrast_list)
# Print the result
print("Overlap of IGSF9B PINK1 PRKN")
[1] "Overlap of IGSF9B PINK1 PRKN"
print(overlap_genes)
 [1] "TPM3"     "TMEM132E" "DNAJC10"  "CSRP2"    "TJP1"     "ZNF207"   "TPD52L2"  "NCK2"     "PRAF2"    "GLS"      "FKBP9"    "PGLS"     "COX2"    
[14] "TFRC"     "CSTB"     "CTSB"     "CLU"      "LAMP1"    "CKMT1B"   "CKMT1A"   "COX7A2"   "ARSA"     "PTMS"     "ATP6V1C1" "PSMA3"    "CNTFR"   
[27] "L1CAM"    "CTNNA1"   "NES"      "ANXA11"   "RAP1GDS1" "GTF2A1"   "RAD23B"   "TPI1"     "RPS18"    "PSME1"    "PPP3CA"   "SEPTIN2"  "PAFAH1B3"
[40] "MAPRE2"   "EFNB3"    "H2BC21"   "ATAT1"    "CEP170"   "STT3B"    "KHSRP"    "ERGIC1"   "DYNLL2"   "PANX1"    "PFDN5"    "TPPP3"    "NAPB"    
[53] "C17orf75" "PLCB1"    "P4HTM"    "PODXL2"   "TMEM63C"  "CDV3"     "RTCB"    
length(overlap_genes)
[1] 59
write.csv(overlap_genes,"/Users/rhalenathomas/Downloads/Move_Data/DarkGenomeResult/omics/OverlapLGeneLists/IGSF9B_PINK1_PRKN_DPE.csv")
print("saved")
[1] "saved"
# PRKN IGSF9B
contrast_list <- c("IGSF9B-KO", "PINK1-KO")
overlap_genes <- get_specific_gene_overlap(filtered_DEP, contrast_list)
# Print the result
print("Overlap of IGSF9B PINK1")
[1] "Overlap of IGSF9B PINK1"
print(overlap_genes)
 [1] "LIN7A"     "DCLK1"     "RNMT"      "DYNC1LI2"  "TGOLN2"    "SPAG9"     "SYNCRIP"   "IDH1"      "AP2A2"     "GPI"       "SNRPA"     "H1-4"     
[13] "DES"       "DDX6"      "MAP4"      "GRN"       "CORO1A"    "YWHAB"     "SDC2"      "HSPA4"     "GPX4"      "ATP6V1A"   "RPL35"     "PAFAH1B1" 
[25] "LMAN1"     "HMGA2"     "TUBA4A"    "CLTC"      "DR1"       "EEF1A2"    "MFGE8"     "AP3B2"     "MOGS"      "SHH"       "ATP2B3"    "LSM12"    
[37] "XKR4"      "MIA3"      "TUBA1A"    "PRUNE1"    "ERC1"      "GATD1"     "LEMD2"     "NBEA"      "CRELD1"    "VPS35"     "ERP44"     "FSD1"     
[49] "TRIM2"     "RAI14"     "MACROH2A2" "SEPTIN3"   "NRBP1"     "DNM3"     
length(overlap_genes)
[1] 54
write.csv(overlap_genes,"/Users/rhalenathomas/Downloads/Move_Data/DarkGenomeResult/omics/OverlapLGeneLists/IGSF9B_PINK1_DPE.csv")
print("saved")
[1] "saved"
# INPP5F IGSF9B
contrast_list <- c("IGSF9B-KO", "INPP5F-KO")
overlap_genes <- get_specific_gene_overlap(filtered_DEP, contrast_list)
# Print the result
print("Overlap of IGSF9B INPP5F")
[1] "Overlap of IGSF9B INPP5F"
print(overlap_genes)
 [1] "SYT5"     "AGRN"     "ASTN1"    "GPAA1"    "ECI2"     "ADGRL2"   "BCHE"     "ITGA5"    "LAMC1"    "TOP1"     "GJA1"     "M6PR"     "COL5A1"  
[14] "MDK"      "IGFBP5"   "MCM3"     "CCN2"     "CLCN6"    "H4C8"     "H4C9"     "H4C6"     "H4C12"    "H4C5"     "H4C13"    "H4C1"     "H4C4"    
[27] "H4C2"     "H4C16"    "SPTBN1"   "BAX"      "ASPH"     "SYPL1"    "EMC4"     "TOR1AIP1" "ATRAID"   "RAPH1"    "H3C14"    "H3C15"    "H3C13"   
[40] "HS2ST1"   "H2AC21"   "SRRM1"    "TOMM5"    "NUP210"   "BRI3BP"   "SEMA4D"   "TSNAX"    "GDF15"    "RAB5IF"   "FUT8"     "MTCH1"    "CNTNAP2" 
[53] "NDRG4"    "PPM1H"    "THSD7A"   "UCHL5"    "GPC6"     "CLIC4"   
length(overlap_genes)
[1] 58
write.csv(overlap_genes,"/Users/rhalenathomas/Downloads/Move_Data/DarkGenomeResult/omics/OverlapLGeneLists/IGSF9B_INPP5F_DPE.csv")
print("saved")
[1] "saved"
# INPP5F SH3GL2
contrast_list <- c("SH3GL2-KO", "INPP5F-KO")
overlap_genes <- get_specific_gene_overlap(filtered_DEP, contrast_list)
# Print the result
print("Overlap of SH3GL2 INPP5F")
[1] "Overlap of SH3GL2 INPP5F"
print(overlap_genes)
 [1] "RAB27B"   "SCD"      "MID1"     "MYO1B"    "NOL3"     "EML2"     "AGR2"     "CST3"     "S100A6"   "ABCB1"    "MTHFD2"   "ANK1"     "MSN"     
[14] "CLIP1"    "SERPINB6" "CAP2"     "TMPO"     "NPTX2"    "P51784"   "MAP2K1"   "GFPT1"    "SRSF5"    "ITIH4"    "OPCML"    "DLG2"     "PTGIS"   
[27] "PCK2"     "ALDH1L2"  "MDGA2"    "AHNAK2"   "Q8IXS6"   "CMIP"     "FAM177A1" "GPC2"     "GPT2"     "SNRNP27"  "ARHGEF2"  "WBP2"     "SPOCK3"  
[40] "FAM107B"  "CYSTM1"   "ALG2"     "POMK"     "DCTPP1"   "ZCCHC3"   "ARMCX1"   "XPR1"     "DNAJB4"   "PCDHA4"   "FNDC3A"   "HYOU1"   
length(overlap_genes)
[1] 51
write.csv(overlap_genes,"/Users/rhalenathomas/Downloads/Move_Data/DarkGenomeResult/omics/OverlapLGeneLists/SH3GL2_INPP5F_DPE.csv")
print("saved")
[1] "saved"
# SNCA A53T pink parkin
contrast_list <- c("PINK1-KO", "PRKN-KO", "SNCA-A53T")
overlap_genes <- get_specific_gene_overlap(filtered_DEP, contrast_list)
# Print the result
print("Overlap of SNCA A53T PINK1 PRKN")
[1] "Overlap of SNCA A53T PINK1 PRKN"
print(overlap_genes)
 [1] "MBNL1"      "PON2"       "PGM3"       "GDAP1"      "NONO"       "SLC1A3"     "PALM2AKAP2" "SEC31A"     "TNPO3"      "E9PJP2"     "RPL28"     
[12] "BET1"       "RPS5"       "RPL21"      "RPS16"      "GOLIM4"     "CRTAP"      "SLC25A12"   "CALB1"      "RPSA"       "RPS2"       "RPL35A"    
[23] "SCP2"       "RPS3"       "AHCY"       "ITGB8"      "RPL10"      "GGCX"       "NNMT"       "RPS10"      "GNAQ"       "COPB1"      "COPA"      
[34] "ATP1B3"     "GNG2"       "EIF4A1"     "RPS20"      "SNAP25"     "RPS7"       "RPS4X"      "RPL30"      "GNAI1"      "RACK1"      "EEF1A1"    
[45] "CNTNAP1"    "RPL24"      "FKBP3"      "DHX9"       "SND1"       "HNRNPLL"    "RBMXL1"     "MRPL9"      "VAT1L"      "CMTM6"      "ATP5IF1"   
[56] "PROCR"      "GMPPB"     
length(overlap_genes)
[1] 57
write.csv(overlap_genes,"/Users/rhalenathomas/Downloads/Move_Data/DarkGenomeResult/omics/OverlapLGeneLists/SNCAA53T_PINK1_PRKN_DPE.csv")
print("saved")
[1] "saved"
# bright genome and IGSF9B
contrast_list <- c("SNCA-A53T", "GBA-KO", "PINK1-KO", "PRKN-KO", "IGSF9B-KO")
overlap_genes <- get_specific_gene_overlap(filtered_DEP, contrast_list)
# Print the result
print("Overlap of SNCA GBA PINK1 PRKN IGSF9B")
[1] "Overlap of SNCA GBA PINK1 PRKN IGSF9B"
print(overlap_genes)
 [1] "NCAM1"    "STXBP1"   "PALM3"    "P4HB"     "CYCS"     "CTSD"     "SNCA"     "NEFM"     "TP53I11"  "DCX"      "CLN5"     "SNCG"     "HRAS"    
[14] "NEFL"     "ANXA2"    "SYP"      "ANXA5"    "GNAO1"    "HSPA5"    "RALA"     "ATP1A3"   "P4HA1"    "GNS"      "PPP3CB"   "SYN1"     "GAP43"   
[27] "EPHB2"    "ACAA2"    "HDGF"     "RPS13"    "GNB1"     "SET"      "PLOD1"    "LGALS3BP" "GALNT2"   "CNTN1"    "DNAJC3"   "STX1A"    "GDAP1L1" 
[40] "CEND1"    "CADM2"    "GLG1"     "CMBL"     "DIRAS2"   "FUCA2"    "TMOD3"    "PLXNA1"  
length(overlap_genes)
[1] 47
write.csv(overlap_genes,"/Users/rhalenathomas/Downloads/Move_Data/DarkGenomeResult/omics/OverlapLGeneLists/SNCAA53T_GBA_PINK1_PRKN_IGSF9B_DPE.csv")
print("saved")
[1] "saved"
# bright genome
contrast_list <- c("SNCA-A53T", "GBA-KO", "PINK1-KO", "PRKN-KO")
overlap_genes <- get_specific_gene_overlap(filtered_DEP, contrast_list)
# Print the result
print("Overlap of SNCA GBA PINK1 PRKN")
[1] "Overlap of SNCA GBA PINK1 PRKN"
print(overlap_genes)
 [1] "HDLBP"      "A0A0J9YYL3" "A0A1P0AYU5" "RPS14"      "HSPA12A"    "OBSCN"      "SNRPE"      "SCFD1"      "RPS3A"      "F8W6I7"     "CD44"      
[12] "H3BQZ7"     "CBX1"       "HNRNPUL1"   "KPNA6"      "SSB"        "PYGL"       "DCN"        "NCL"        "HNRNPA2B1"  "ATP2B4"     "FKBP2"     
[23] "EEF1D"      "PRDX6"      "RPS19"      "SRP9"       "RPS8"       "RPS23"      "RPL23A"     "RPL10A"     "ABAT"       "ERH"        "NUCB1"     
[34] "CRYZ"       "AHNAK"      "TRIM28"     "FNDC3B"     "GOLPH3"     "CTPS2"      "SEC23IP"   
length(overlap_genes)
[1] 40
write.csv(overlap_genes,"/Users/rhalenathomas/Downloads/Move_Data/DarkGenomeResult/omics/OverlapLGeneLists/SNCAA53T_GBA_PINK1_PRKN_DPE.csv")
print("saved")
[1] "saved"

# bright genome
contrast_list <- c("SH3GL2-KO", "INPP5F-KO","IGSF9B-KO")
overlap_genes <- get_specific_gene_overlap(filtered_DEP, contrast_list)
# Print the result
print("Overlap of SH3GL2 INPP5F IGSF9B")
[1] "Overlap of SH3GL2 INPP5F IGSF9B"
print(overlap_genes)
 [1] "APBB1"    "PCDH7"    "SLIT2"    "ATP6V1G2" "PCSK1"    "DCC"      "EPHA4"    "PLTP"     "GFRA1"    "ANK2"     "APBA1"    "PCDH1"    "CAMK2G"  
[14] "PLCB4"    "DECR1"    "BRINP3"   "NEGR1"    "ACOT1"    "CNTN4"    "NLGN4X"   "IGSF1"    "DLG3"     "CCDC51"   "SERPINI1" "EDEM3"    "CHODL"   
[27] "CRTAC1"   "NLGN3"    "MYOF"     "SEMA5B"   "EPHA6"   
length(overlap_genes)
[1] 31
write.csv(overlap_genes,"/Users/rhalenathomas/Downloads/Move_Data/DarkGenomeResult/omics/OverlapLGeneLists/IGSF9B_INPP5F_SH3GL2_DPE.csv")
print("saved")
[1] "saved"
# IGSF9B pink parkin SNCA
contrast_list <- c("PINK1-KO", "PRKN-KO", "IGSF9B-KO","SNCA-A53T")
overlap_genes <- get_specific_gene_overlap(filtered_DEP, contrast_list)
# Print the result
print("Overlap of IGSF9B PINK1 PRKN SNCA-A53T")
[1] "Overlap of IGSF9B PINK1 PRKN SNCA-A53T"
print(overlap_genes)
 [1] "TMED7-TICAM2" "SCARB2"       "RPS24"        "UGP2"         "PTPRD"        "NPC2"         "PTMA"         "FXYD7"        "RPN1"         "GAA"         
[11] "G6PD"         "PCNA"         "GLB1"         "ANXA7"        "STT3A"        "TMED10"       "SSR4"         "BASP1"        "LMAN2"        "INA"         
[21] "P3H1"         "HEXB"         "NT5DC3"       "FKBP10"       "MBOAT7"       "NUCKS1"       "ASAP1"        "TLN1"         "FKBP7"       
length(overlap_genes)
[1] 29
write.csv(overlap_genes,"/Users/rhalenathomas/Downloads/Move_Data/DarkGenomeResult/omics/OverlapLGeneLists/SNCAA53T_IGSF9B_PINK1_PRKN_DPE.csv")
print("saved")
[1] "saved"
contrast_list <- c("PINK1-KO", "PRKN-KO", "IGSF9B-KO","GBA-KO")
overlap_genes <- get_specific_gene_overlap(filtered_DEP, contrast_list)
# Print the result
print("Overlap of IGSF9B PINK1 PRKN GBA")
[1] "Overlap of IGSF9B PINK1 PRKN GBA"
print(overlap_genes)
 [1] "VTA1"     "LMNA"     "PRCP"     "MAN2B1"   "GLRX3"    "OAT"      "NAGA"     "VDAC1"    "HMGCS1"   "PDAP1"    "FLNC"     "CELF1"    "RAB3C"   
[14] "NAPG"     "MAP1LC3A" "SLC25A13" "SAMM50"  
length(overlap_genes)
[1] 17
write.csv(overlap_genes,"/Users/rhalenathomas/Downloads/Move_Data/DarkGenomeResult/omics/OverlapLGeneLists/GBA_IGSF9B_PINK1_PRKN_DPE.csv")
print("saved")
[1] "saved"


# A53T IGSF9B
contrast_list <- c("IGSF9B-KO", "SNCA-A53T")
overlap_genes <- get_specific_gene_overlap(filtered_DEP, contrast_list)
# Print the result
print("Overlap of IGSF9B SNCA A53T")
[1] "Overlap of IGSF9B SNCA A53T"
print(overlap_genes)
 [1] "SDCBP"    "DNAJC6"   "PALM"     "PAK3"     "CLSTN1"   "ACYP1"    "UCHL1"    "MAPT"     "STMN1"    "CANX"     "PRKAR2B"  "PFN2"     "PPP3CC"  
[14] "MARCKSL1" "RAC1"     "TUBB2A"   "CRMP1"    "DPYSL3"   "GNAS"     "SLC27A4"  "RHOT2"    "CHMP6"    "ZC2HC1A"  "TMX3"     "TM9SF3"   "GGT7"    
[27] "NRXN1"   
length(overlap_genes)
[1] 27
write.csv(overlap_genes,"/Users/rhalenathomas/Downloads/Move_Data/DarkGenomeResult/omics/OverlapLGeneLists/IGSF9B_SNCAA53T_DPE.csv")
print("saved")
[1] "saved"
# A53T IGSF9B
contrast_list <- c("IGSF9B-KO", "SH3GL2-KO")
overlap_genes <- get_specific_gene_overlap(filtered_DEP, contrast_list)
# Print the result
print("Overlap of IGSF9B SH3GL2")
[1] "Overlap of IGSF9B SH3GL2"
print(overlap_genes)
 [1] "KPNA4"   "IDH3B"   "STAMBP"  "CD63"    "SRC"     "HMGA1"   "STOM"    "MARCKS"  "TSPAN7"  "PCBP3"   "IGBP1"   "TGFBI"   "TSC22D1" "MAVS"    "ADCK1"  
[16] "SCAMP5"  "CD99L2"  "PDXP"    "SH3GL2"  "SEZ6L"   "ACTR3B"  "EPDR1"   "SLC8A2"  "TLN2"    "NUMBL"  
length(overlap_genes)
[1] 25
write.csv(overlap_genes,"/Users/rhalenathomas/Downloads/Move_Data/DarkGenomeResult/omics/OverlapLGeneLists/IGSF9B_SH3GL2_DPE.csv")
print("saved")
[1] "saved"
# A53T IGSF9B
contrast_list <- c("IGSF9B-KO", "IP6K2-KO")
overlap_genes <- get_specific_gene_overlap(filtered_DEP, contrast_list)
# Print the result
print("Overlap of IGSF9B IP6K")
[1] "Overlap of IGSF9B IP6K"
print(overlap_genes)
 [1] "SNX4"     "PENK"     "SERPINE2" "NGFR"     "MGST1"    "PTN"      "IDH3A"    "SYNJ2BP"  "SARNP"    "TUSC3"    "ANO6"     "TCEAL5"   "EARS2"   
[14] "SNX30"    "ATCAY"    "THNSL1"   "SHC3"     "PPP1R10"  "VAT1"     "TM9SF2"   "PACSIN1"  "SLC5A7"   "TBC1D24"  "CAMK2A"   "PPP2R2C" 
length(overlap_genes)
[1] 25
write.csv(overlap_genes,"/Users/rhalenathomas/Downloads/Move_Data/DarkGenomeResult/omics/OverlapLGeneLists/IGSF9B_IP6K2_DPE.csv")
print("saved")
[1] "saved"
# A53T PINK1
contrast_list <- c("PINK1-KO", "SNCA-A53T")
overlap_genes <- get_specific_gene_overlap(filtered_DEP, contrast_list)
# Print the result
print("Overlap of PINK1KO SNCA A53T")
[1] "Overlap of PINK1KO SNCA A53T"
print(overlap_genes)
 [1] "TARDBP" "DDX17"  "NPM1"   "RPL8"   "SEC22B" "RPLP0"  "RAB3A"  "SFPQ"   "RPL22"  "RPS9"   "HNRNPM" "HNRNPK" "RPL7A"  "TOP2B"  "DNM1"   "GOLGB1"
[17] "RAB35"  "SF3B3"  "Q5T0I0" "PLPPR3" "MB21D2" "CMAS"   "BRSK1"  "MAP6"  
length(overlap_genes)
[1] 24
write.csv(overlap_genes,"/Users/rhalenathomas/Downloads/Move_Data/DarkGenomeResult/omics/OverlapLGeneLists/PINK1_SNCAA53T_DPE.csv")
print("saved")
[1] "saved"
# A53T PINK1 GBA
contrast_list <- c("PINK1-KO", "SNCA-A53T","GBA-KO")
overlap_genes <- get_specific_gene_overlap(filtered_DEP, contrast_list)
# Print the result
print("Overlap of PINK1KO SNCA A53T and GBA")
[1] "Overlap of PINK1KO SNCA A53T and GBA"
print(overlap_genes)
 [1] "HNRNPU"   "RPL5"     "HNRNPC"   "B4E171"   "HNRNPH1"  "HMGN1"    "RPL17"    "DDX5"     "HSPA4L"   "CA2"      "XRCC6"    "SNRPB"    "LMNB1"   
[14] "RPL23"    "NCBP1"    "ATP6V0A1" "THRAP3"  
length(overlap_genes)
[1] 17
write.csv(overlap_genes,"/Users/rhalenathomas/Downloads/Move_Data/DarkGenomeResult/omics/OverlapLGeneLists/PINK1_SNCAA53T_GBA_DPE.csv")
print("saved")
[1] "saved"
# A53T PINK1 IGSF9B
contrast_list <- c("PINK1-KO", "SNCA-A53T","IGSF9B-KO")
overlap_genes <- get_specific_gene_overlap(filtered_DEP, contrast_list)
# Print the result
print("Overlap of PINK1KO SNCA A53T and IGSF9B")
[1] "Overlap of PINK1KO SNCA A53T and IGSF9B"
print(overlap_genes)
 [1] "SHTN1"  "SNAP91" "TUBB4A" "NSF"    "ACADVL" "RPL26"  "RHOB"   "CXADR"  "CKAP4"  "OS9"    "TUBB3"  "MVP"    "TMED2"  "PRRT2"  "NAT10"  "WDR37" 
length(overlap_genes)
[1] 16
write.csv(overlap_genes,"/Users/rhalenathomas/Downloads/Move_Data/DarkGenomeResult/omics/OverlapLGeneLists/PINK1_SNCAA53T_IGSF9B_DPE.csv")
print("saved")
[1] "saved"
# dark genome
contrast_list <- c("SH3GL2-KO", "INPP5F-KO","IGSF9B-KO", "IP6K2-KO")
overlap_genes <- get_specific_gene_overlap(filtered_DEP, contrast_list)
# Print the result
print("Overlap of SH3GL2 INPP5F IGSF9B")
[1] "Overlap of SH3GL2 INPP5F IGSF9B"
print(overlap_genes)
 [1] "PCP4L1"  "SYNM"    "CSPG5"   "UTS2"    "VAMP1"   "NOVA1"   "DYNLT3"  "CARTPT"  "PDK4"    "LBH"     "FAM162A" "SLC6A17" "SLC17A6" "SUN2"   
length(overlap_genes)
[1] 14
write.csv(overlap_genes,"/Users/rhalenathomas/Downloads/Move_Data/DarkGenomeResult/omics/OverlapLGeneLists/IGSF9B_INPP5F_SH3GL2_IP6K2_DPE.csv")
print("saved")
[1] "saved"

Individual contrasts


contrast_list <- c("SNCA-A53T")
overlap_genes <- get_specific_gene_overlap(filtered_DEP, contrast_list)
# Print the result
print("Unique to SNCA A53T")
[1] "Unique to SNCA A53T"
print(overlap_genes)
 [1] "ABHD6"    "NUDT9"    "AGAP1"    "GUCY1B1"  "GOSR1"    "COPZ1"    "DDX3Y"    "NRAS"     "QDPR"     "ARF4"     "TAGLN2"   "GNG4"     "EIF5"    
[14] "MRPS5"    "SF3B2"    "XKR7"     "RPL11"    "ASRGL1"   "PLD3"     "FAM114A1" "HYCC2"    "HSD17B11" "TTN"      "LRRC59"   "FAM241B"  "SDF2"    
[27] "CADM1"    "UBE2O"    "SAR1A"    "BPNT2"    "BSN"      "ATP8A1"   "NPTN"    
length(overlap_genes)
[1] 33
write.csv(overlap_genes,"/Users/rhalenathomas/Downloads/Move_Data/DarkGenomeResult/omics/OverlapLGeneLists/SNCAA53T_DPE.csv")
print("saved")
[1] "saved"
contrast_list <- c("GBA-KO")
overlap_genes <- get_specific_gene_overlap(filtered_DEP, contrast_list)
# Print the result
print("Unique to GBA KO")
[1] "Unique to GBA KO"
print(overlap_genes)
[1] "MADD"    "IDH3G"   "PLXNC1"  "NNT"     "RHEB"    "HSDL1"   "ABCF1"   "RAPGEF4" "GDA"    
length(overlap_genes)
[1] 9
write.csv(overlap_genes,"/Users/rhalenathomas/Downloads/Move_Data/DarkGenomeResult/omics/OverlapLGeneLists/GBA_DPE.csv")
print("saved")
[1] "saved"
contrast_list <- c("PINK1-KO")
overlap_genes <- get_specific_gene_overlap(filtered_DEP, contrast_list)
# Print the result
print("Unique to PINK1 KO")
[1] "Unique to PINK1 KO"
print(overlap_genes)
  [1] "A0A087WTM1" "A0A087WY61" "CD99"       "MYEF2"      "A0A0A0MR09" "ILK"        "ENAH"       "QARS1"      "DLG1"       "TCOF1"      "UBE3A"     
 [12] "PPIG"       "RMND1"      "RABGAP1L"   "IARS1"      "PTBP1"      "ILF2"       "PREB"       "PLRG1"      "HNRNPAB"    "SKP1"       "ALYREF"    
 [23] "CELF2"      "ADCYAP1R1"  "HSPA8"      "LAMTOR1"    "UBAP2L"     "F8WE88"     "ARFGAP2"    "RPL36A"     "TMEM199"    "SRSF1"      "FARSA"     
 [34] "RPL18A"     "HIP1"       "HMGN4"      "HNRNPR"     "CHMP2A"     "AHCYL1"     "PLIN3"      "SF3B1"      "CPD"        "SEC24D"     "UFL1"      
 [45] "ABCA8"      "KRAS"       "FGF1"       "EPRS1"      "HSP90AA1"   "PFKM"       "SNRPB2"     "PYGB"       "DARS1"      "IGFBP4"     "RPL12"     
 [56] "HNRNPH3"    "FUS"        "ATP6V1E1"   "USP8"       "LSS"        "HNRNPA3"    "MARS1"      "EIF6"       "NUTF2"      "PPP1CB"     "RPS11"     
 [67] "SNRPG"      "SNRPD1"     "SNRPD3"     "ACTA2"      "RPL31"      "ACY1"       "LMNB2"      "KHDRBS1"    "SF3A3"      "ILF3"       "CBX3"      
 [78] "CUL3"       "SEPTIN7"    "H2AC20"     "SF3B4"      "MRPL14"     "PRPF8"      "PPP1R21"    "DGLUCY"     "CENPV"      "CCAR2"      "GPD1L"     
 [89] "NUP43"      "CTNNBL1"    "HDAC2"      "SLC25A46"   "FAF2"       "VMP1"       "API5"       "EHD4"       "RPAP3"      "FARSB"      "SLTM"      
[100] "HDAC6"      "CADPS"      "LSM2"       "SF3B6"      "DAAM1"      "ATP6V1D"   
length(overlap_genes)
[1] 105
write.csv(overlap_genes,"/Users/rhalenathomas/Downloads/Move_Data/DarkGenomeResult/omics/OverlapLGeneLists/PINK1_DPE.csv")
print("saved")
[1] "saved"
contrast_list <- c("PRKN-KO")
overlap_genes <- get_specific_gene_overlap(filtered_DEP, contrast_list)
# Print the result
print("Unique to PRKN KO")
[1] "Unique to PRKN KO"
print(overlap_genes)
  [1] "HMOX2"      "A0A087WTF6" "A0A087WUC6" "MTHFD1L"    "PSME2"      "PSMC6"      "ELAVL2"     "ATP6AP1"    "HSPA1B"     "HSPA1A"     "KAZN"      
 [12] "BRAF"       "CTNNB1"     "SUCLA2"     "RAPGEF2"    "PDE10A"     "ABCD3"      "CLUH"       "IMPDH2"     "NDUFA10"    "ADSL"       "NAXD"      
 [23] "CUL4B"      "AASS"       "DLAT"       "SH3PXD2B"   "ACO2"       "ENSA"       "SEC13"      "MYL6"       "IMMT"       "DTNBP1"     "EIF4E"     
 [34] "COPS6"      "NDUFV2"     "WASHC5"     "PLOD2"      "PAICS"      "NPEPPS"     "ABLIM2"     "PXN"        "MTHFD1"     "SEC23A"     "MYG1"      
 [45] "LIMA1"      "ARL1"       "F8W809"     "GPATCH4"    "LIMS1"      "G3V180"     "APOO"       "PIN4"       "SQLE"       "H3BNC9"     "LMF1"      
 [56] "ACTN4"      "TTC27"      "NAA38"      "TUBB6"      "SARS2"      "AP3B1"      "PDHX"       "PSMD14"     "PPP6C"      "TNPO2"      "SCAMP3"    
 [67] "ERC2"       "ARPC3"      "CAPN5"      "NDUFA2"     "NDUFS5"     "TIMM8A"     "NRP2"       "OGA"        "RANBP6"     "ROCK2"      "CSDE1"     
 [78] "STAM2"      "ATP5PD"     "PLPBP"      "LYPLA2"     "IPO7"       "ECEL1"      "AIFM1"      "SOD1"       "PGK1"       "GAPDH"      "ATP1A1"    
 [89] "ALDH2"      "ATP5F1B"    "ENO1"       "PFN1"       "HSP90AB1"   "ACAA1"      "DLD"        "ESD"        "SLC2A3"     "PC"         "SLC25A6"   
[100] "CKB"        "RNH1"       "TPT1"       "ETFA"       "AKR1A1"     "GSPT1"      "NCK1"       "PSMC3"      "VCL"        "CALB2"      "ACP1"      
[111] "TARS1"      "MAPK1"      "ALDH4A1"    "PRDX3"      "ATP5F1D"    "ADSS2"      "SLC7A1"     "HIBADH"     "ATIC"       "KIF5B"      "AGL"       
[122] "PSMC2"      "PGM1"       "GNL1"       "ETFB"       "RBMX"       "HSPA9"      "ADCY8"      "EIF2S3"     "USP5"       "GNPDA1"     "ATP5PO"    
[133] "PREP"       "IDH2"       "TUFM"       "AARS1"      "HINT1"      "EMD"        "CCT4"       "RAB7A"      "ALDH3A2"    "CAPZA1"     "CRIP2"     
[144] "SLC25A1"    "ARFIP1"     "SUCLG1"     "PRKAG1"     "CSE1L"      "VCP"        "ATP5MJ"     "EEFSEC"     "ARPC4"      "DSTN"       "RAB8A"     
[155] "UBE2M"      "SST"        "RAN"        "AP2B1"      "PPP2R2A"    "MRPS15"     "TFAM"       "GLO1"       "AKR1C1"     "SSBP1"      "PTPN11"    
[166] "APLP2"      "C1QBP"      "VAC14"      "AIMP1"      "TRAP1"      "TRAF2"      "PRKAA1"     "MRPL49"     "SLC39A6"    "PICALM"     "NAE1"      
[177] "CTTN"       "HES1"       "KPNB1"      "GAPVD1"     "RAB3GAP1"   "PEA15"      "TAB1"       "CDC37"      "NDUFA5"     "HADH"       "LRRFIP1"   
[188] "MTUS2"      "ACADM"      "SARS1"      "NT5DC1"     "ATG9B"      "HIBCH"      "PKN3"       "SARM1"      "VPS13C"     "FASTKD5"    "HUWE1"     
[199] "STX12"      "FUNDC1"     "SULF1"      "TPH2"       "GSPT2"      "LGI2"       "NDUFAF2"    "LRRC47"     "ARMC10"     "RDH11"      "LARP4B"    
[210] "GCN1"       "MRPS31"     "NECTIN2"    "TFG"        "STAM"       "GCDH"       "IGSF8"      "PHYHIPL"    "IPO9"       "PSMB7"      "APOL2"     
[221] "CORO1B"     "CNPY3"      "MRPS26"     "LNPK"       "RTN4"       "NANS"       "OLA1"       "ABHD10"     "ETNK2"      "CISD1"      "LMCD1"     
[232] "PTGFRN"     "ANKFY1"     "ATXN10"     "COPG2"      "STK39"      "TRMT112"    "VPS28"      "DNAJC12"    "ZMYND8"     "DDX19B"     "MAGED2"    
[243] "PSMD13"     "RUVBL2"     "PLAA"       "RUVBL1"     "MRPS28"     "MRPS17"     "TMA7"       "ACOT9"      "LUC7L2"     "STRAP"      "PPME1"     
[254] "CDC42BPB"   "HEBP2"      "PSAT1"     
length(overlap_genes)
[1] 256
write.csv(overlap_genes,"/Users/rhalenathomas/Downloads/Move_Data/DarkGenomeResult/omics/OverlapLGeneLists/PRKN_DPE.csv")
print("saved")
[1] "saved"
contrast_list <- c("IGSF9B-KO")
overlap_genes <- get_specific_gene_overlap(filtered_DEP, contrast_list)
# Print the result
print("Unique to IGSF9B")
[1] "Unique to IGSF9B"
print(overlap_genes)
  [1] "ESYT2"               "ILVBL"               "DENND3"              "CASTOR2"             "FAM171A2"            "MCRIP1"             
  [7] "SLC35A4"             "DNASE2"              "KIF2A"               "MYO1C"               "DFFA"                "MANBA"              
 [13] "RNASET2"             "PODXL"               "ARID1A"              "SDHD"                "COX7A2L"             "UBFD1"              
 [19] "ABLIM1"              "ADAM10"              "EI24"                "PDCD5"               "TPP1"                "CPLX1"              
 [25] "PSMA7"               "TIMM23"              "UQCRQ"               "CLGN"                "SPTBN2"              "KIF3B"              
 [31] "SNPH"                "DEGS1"               "SCAMP2"              "PGRMC2"              "PFDN6"               "RER1"               
 [37] "SPTLC1"              "HMGB3"               "STX7"                "YKT6"                "FABP7"               "SEPTIN4"            
 [43] "SRGAP3"              "TXNL1"               "SYNJ1"               "PROM1"               "TSPAN6"              "NDUFB5"             
 [49] "NDUFB3"              "AP1G1"               "SGTA"                "SLC25A20"            "NUDT21"              "CALU"               
 [55] "EXTL3"               "MFSD11"              "KIF5C"               "SELENOF"             "TSPAN2"              "TSPAN3"             
 [61] "DPM1"                "TIMM17B"             "CUTA"                "PFDN1"               "ABCB7"               "SRGAP2"             
 [67] "ATP9A"               "CLASP2"              "PPFIA3"              "TBCA"                "MPDU1"               "MACROH2A1"          
 [73] "PEX14"               "NDUFB1"              "ERLIN1"              "HSBP1"               "BANF1"               "TIPRL"              
 [79] "PPM1B"               "ADAP1"               "ATP6AP2"             "EIF3G"               "EIF3J"               "ATRN"               
 [85] "DGAT1"               "ARL6IP5"             "FLOT1"               "TRIO"                "RSL1D1"              "B3GAT3"             
 [91] "DDHD2"               "NFASC"               "TMCC1"               "ENDOD1"              "WDR47"               "YIF1A"              
 [97] "NDUFB4"              "SBF1"                "VAPB"                "SNAPIN"              "NDUFC2"              "OXSR1"              
[103] "GGPS1"               "BAG2"                "NDUFB10"             "TOMM40"              "PEX11B"              "HPRT1"              
[109] "ATP6"                "IGF2"                "APOE"                "APOC3"               "FTH1"                "GBA1"               
[115] "HLA-A"               "RPN2"                "SCG5"                "ATP5MC1"             "ITGB1"               "GLA"                
[121] "HEXA"                "EPHX1"               "LDHB"                "PSAP"                "LAMB1"               "ENO2"               
[127] "CLTA"                "ANXA4"               "COX6C"               "SMIM13"              "RAP2A"               "TXN"                
[133] "CTSA"                "CHGA"                "ACP2"                "MAP2"                "DBT"                 "RALB"               
[139] "TOP2A"               "UBL4A"               "IGF2R"               "COL6A1"              "LAMP2"               "PRKAR2A"            
[145] "MIF"                 "UCHL3"               "CD46"                "ARSB"                "RPA2"                "COX7C"              
[151] "H1-5"                "H1-3"                "H1-2"                "GOT1"                "NDUFB7"              "GM2A"               
[157] "SON"                 "GNAZ"                "RAB3B"               "GSTM3"               "SYT1"                "OSBP"               
[163] "FBL"                 "FDXR"                "GCSH"                "CFL1"                "EEF1B2"              "GRK2"               
[169] "PSMA1"               "YWHAQ"               "MARK3"               "PSMB5"               "TMOD1"               "LAP3"               
[175] "IMPA1"               "GDI1"                "TIA1"                "UQCRC1"              "STIP1"               "S100A11"            
[181] "GALNS"               "MYH10"               "ADD1"                "BSG"                 "PPM1A"               "HMGCL"              
[187] "P36268"              "DLST"                "NUP62"               "LIPA"                "COL18A1"             "MDH1"               
[193] "HADHA"               "CETN2"               "CD200"               "ACTR1B"              "EPS15"               "CASP3"              
[199] "ECE1"                "SSR1"                "MAP1B"               "RAP1GAP"             "CAPZB"               "TFPI2"              
[205] "PIP4K2A"             "CD151"               "HSPA13"              "AMPH"                "INPP1"               "HARS2"              
[211] "PSEN1"               "TSC2"                "GSK3B"               "NT5C2"               "SEPHS1"              "CPT1A"              
[217] "ST13"                "HCFC1"               "ALDH5A1"             "PSMD7"               "KIF11"               "MVD"                
[223] "CTSC"                "PTTG1IP"             "SLC16A1"             "RAD23A"              "ALDH18A1"            "MFAP2"              
[229] "AFDN"                "HNRNPH2"             "BID"                 "ARPP19"              "AP1S2"               "CORO7"              
[235] "EPPK1"               "SEC61B"              "S100A10"             "UBE2N"               "RPL27"               "PCBD1"              
[241] "SEC61A1"             "DAD1"                "PKIA"                "SUMO2"               "UFM1"                "AP1S1"              
[247] "YWHAG"               "YWHAE"               "ARF6"                "RPS6"                "RBX1"                "RPL32"              
[253] "PPIA"                "VAMP2"               "YWHAZ"               "PPP2CA"              "SEC11A"              "UBE2L3"             
[259] "TUBB4B"              "GTF2I"               "PIP4K2B"             "SLC35A1"             "ARG2"                "MRPS11"             
[265] "ARF5"                "H3-3A"               "H3-3B"               "HSPG2"               "SLC25A3"             "CDK5"               
[271] "TIAL1"               "CTBS"                "CAP1"                "ATP2B2"              "OCRL"                "SLC25A11"           
[277] "PTS"                 "KLC1"                "ARHGAP1"             "GOLGA3"              "DMTN"                "PPID"               
[283] "SCRN3"               "KIF1A"               "SCRN1"               "ANK3"                "PAK1"                "NME3"               
[289] "MAD2L1"              "UBE2V1"              "PEDS1-UBE2V1"        "DYNC1I2"             "TMED1"               "MTX1"               
[295] "CAMK2B"              "DCTN2"               "STIM1"               "ITGA7"               "SPTAN1"              "HNRNPD"             
[301] "DAG1"                "MLEC"                "TTLL12"              "MPP2"                "DCTN1"               "FLOT2"              
[307] "INPP5A"              "CLINT1"              "LBR"                 "SPCS2"               "EMC2"                "PSMD6"              
[313] "RRS1"                "POSTN"               "PDIA6"               "PPP2R5B"             "RCN1"                "SF1"                
[319] "MAPRE1"              "RAB30"               "ITSN1"               "TBCE"                "UBE2V2"              "VAMP3"              
[325] "DPYSL2"              "CPSF6"               "SMN2"                "SMN1"                "TST"                 "HAGH"               
[331] "PTPRO"               "HNRNPUL2"            "CCDC88A"             "LGALSL"              "VPS26B"              "CCDC184"            
[337] "HSD17B12"            "RAB6D"               "SDK2"                "TMEM97"              "YIF1B"               "MEST"               
[343] "NOMO2"               "WDR44"               "SAMD4B"              "CLVS2"               "TPRG1L"              "FNBP1L"             
[349] "GPR158"              "WLS"                 "Q5TF21"              "MICOS10"             "WASHC2A"             "PPP2R2D"            
[355] "MBLAC2"              "LMBRD2"              "IQSEC1"              "CARMIL2"             "RALGAPA1"            "TCEAL6"             
[361] "REEP3"               "ARMC6"               "JMJD6"               "PPP1R18"             "SLC48A1"             "EDC4"               
[367] "SCYL2"               "CNNM4"               "ERICH5"              "MEAK7"               "PGM2L1"              "AAGAB"              
[373] "TMEM65"              "NCEH1"               "CPLX2"               "MOXD1"               "CYP20A1"             "POGLUT2"            
[379] "TMEM205"             "ISLR2"               "APOOL"               "PACS1"               "RAB11FIP1"           "HSDL2"              
[385] "CRACD"               "GPRIN3"              "TOM1L2"              "TMTC3"               "IKBIP"               "UBE2R2"             
[391] "TLCD3B"              "RUFY3"               "EPM2AIP1"            "TAOK1"               "MOB1B"               "CHMP1B"             
[397] "MICAL3"              "NUP54"               "KIF21A"              "TMED4"               "GALNT7"              "MAGI2"              
[403] "USP48"               "CAND1"               "OSTM1"               "DDX42"               "NDUFA11"             "DOLPP1"             
[409] "GPSM1"               "NUDCD3"              "SLC44A2"             "BRSK2"               "SULF2"               "SIRT2"              
[415] "NRM"                 "SMAP1"               "KIAA0319L"           "NUP93"               "ABHD12"              "SLC43A2"            
[421] "MMGT1"               "CALHM5"              "KCNRG"               "JAGN1"               "COMMD1"              "EMC1"               
[427] "AMER2"               "GOLM1"               "COLGALT1"            "SUMF2"               "TMEM87A"             "TXNDC5"             
[433] "NECAP1"              "CAMKV"               "PLA2G15"             "Q8NCU8"              "MROH1"               "EHBP1"              
[439] "MCU"                 "NUP37"               "NLGN2"               "CADM4"               "FGFBP3"              "UBA3"               
[445] "C18orf32"            "GPX8"                "RAPGEF6"             "C16orf78"            "PDCD6IP"             "PSPC1"              
[451] "PPM1E"               "JDP2"                "LZIC"                "DDX1"                "H1-10"               "NCSTN"              
[457] "TM9SF4"              "WASF1"               "SLC9A6"              "NDRG1"               "NUP205"              "TTC9"               
[463] "SORL1"               "GGH"                 "NRCAM"               "KIFAP3"              "PTPRN2"              "USP9X"              
[469] "BORCS5"              "UBE2E3"              "NCLN"                "CCDC47"              "TMEM230"             "FUBP1"              
[475] "VTI1A"               "MCUR1"               "TOMM6"               "ARL8A"               "CCDC127"             "EFHD2"              
[481] "PYCR2"               "DCPS"                "PPP1R14B"            "ISOC1"               "FOXRED1"             "RAB39B"             
[487] "ERLEC1"              "DAZAP1"              "SGTB"                "CYFIP2"              "CNRIP1"              "LINGO1"             
[493] "OTUB1"               "CERS2"               "SFRP2"               "CDK5RAP3"            "FAM210B"             "PHACTR3"            
[499] "PRRC1"               "VSTM2L"              "RUNDC3B"             "NAP1L5"              "AGAP3"               "MIA2"               
[505] "NEDD4L"              "MAGI1"               "PIGS"                "YME1L1"              "TBCB"                "SEC62"              
[511] "TSC22D3"             "TTC1"                "PHB2"                "ATXN2"               "SIGMAR1"             "EBNA1BP2"           
[517] "H2BC13"              "ECSIT"               "SYT3"                "TXNDC17"             "NUDT16L1"            "SDF4"               
[523] "ESYT1"               "TMEM43"              "LMF2"                "TUBB2B"              "TMEM109"             "PBDC1"              
[529] "PTDSS2"              "TMED9"               "ACAT2"               "AP1M1"               "RAB34"               "SEMA4C"             
[535] "YIPF3"               "NDEL1"               "ROGDI"               "PITHD1"              "MAP1LC3B"            "UBA5"               
[541] "KLC2"                "HDHD2"               "MAGT1"               "LMAN2L"              "SIL1"                "SH3BGRL3"           
[547] "SLC38A1"             "DPAGT1"              "POFUT1"              "PIGU"                "CLSTN2"              "EPB41L1"            
[553] "SMDT1"               "PRR36"               "REEP1"               "SFXN1"               "COG4"                "NMNAT1"             
[559] "TMEM165"             "GLOD4"               "PCDH9"               "MCCC2"               "APMAP"               "NPHS2"              
[565] "DYNLRB1"             "EMC7"                "PFDN4"               "EIF2B3"              "RAB6B"               "TOMM22"             
[571] "LRRC4B"              "RBM12"               "STAU2"               "SHFL"                "TMEM106B"            "AGPAT5"             
[577] "CYRIB"               "EXOC1"               "TMEM38B"             "NDUFB11"             "OCIAD1"              "BABAM2"             
[583] "DPP3"                "SCN3A"               "SCN3B"               "TERF2IP"             "UGGT1"               "ERAP1"              
[589] "CHMP5"               "HACD3"               "KCMF1"               "TBC1D7"              "TBC1D7-LOC100130357" "TOMM7"              
[595] "CAMSAP3"             "DPM3"                "NCDN"                "MRC2"                "CPNE7"               "EXTL2"              
[601] "DNAJB11"             "SEL1L"               "PEF1"                "ZMYM2"               "SLC25A10"            "CLIP2"              
[607] "CFDP1"               "SEC63"               "CHORDC1"             "UBQLN2"              "PCYOX1"              "PFDN2"              
[613] "PUF60"               "NAGK"                "SH3BGRL2"            "PURG"                "GGA1"                "JPT1"               
[619] "TNIK"                "PITPNC1"             "MAN1B1"              "CORO1C"              "HPCAL4"              "MYO6"               
[625] "UBQLN1"              "SYNRG"               "SSR3"                "FAF1"                "MINPP1"              "NOVA2"              
[631] "NSFL1C"              "MAPK8IP3"            "USP24"               "AGTPBP1"             "MAPRE3"              "CORO2B"             
[637] "NUDC"                "MAN2B2"              "EFR3B"               "DIS3"                "GSTK1"               "LAMTOR2"            
[643] "CARHSP1"             "SUGT1"               "COQ6"                "NSG2"                "SH3GLB1"             "DHRS7"              
[649] "TMED5"               "TMED7"               "HDGFL3"              "RABGAP1"             "TMED3"               "WNK2"               
[655] "KIF3A"               "USP15"               "MYO5A"               "RBM7"                "TIMM22"              "TIMM10B"            
[661] "IER3IP1"             "LRRFIP2"             "SPIN1"               "SPCS1"               "NDUFB9"              "FAM169A"            
length(overlap_genes)
[1] 666
write.csv(overlap_genes,"/Users/rhalenathomas/Downloads/Move_Data/DarkGenomeResult/omics/OverlapLGeneLists/IGSF9B_DPE.csv")
print("saved")
[1] "saved"
contrast_list <- c("INPP5F-KO")
overlap_genes <- get_specific_gene_overlap(filtered_DEP, contrast_list)
# Print the result
print("Unique to INPP5F")
[1] "Unique to INPP5F"
print(overlap_genes)
 [1] "PIGBOS1" "CLIC1"   "STX16"   "U2SURP"  "NACAD"   "XPOT"    "STX6"    "SIN3B"   "DAB1"    "TUSC2"   "ACTL6B"  "ZRANB2"  "BAG3"    "CFB"     "ASS1"   
[16] "P01861"  "APOH"    "HPX"     "S100B"   "SNRNP70" "SLC2A1"  "POLR2E"  "AK4"     "ERP29"   "GCHFR"   "SHMT2"   "GARS1"   "NSG1"    "SLC1A4"  "SUB1"   
[31] "MANF"    "TRA2B"   "SRSF2"   "PPARD"   "FLII"    "SRSF6"   "SQSTM1"  "PRP4K"   "IDI1"    "SAFB2"   "SMC1A"   "CHD4"    "RNPS1"   "TERF2"   "PTPRN"  
[46] "UBR4"    "ARFGEF3" "ARSK"    "ARMCX2"  "NDUFAF7" "MICALL1" "PRUNE2"  "COPS9"   "KCTD12"  "PPP1R9B" "CNN2"    "SF3B5"   "C1QTNF4" "SPRY4"   "PNN"    
[61] "GHITM"   "EHMT1"   "GMPR2"   "TAGLN3" 
length(overlap_genes)
[1] 64
write.csv(overlap_genes,"/Users/rhalenathomas/Downloads/Move_Data/DarkGenomeResult/omics/OverlapLGeneLists/INPP5F_DPE.csv")
print("saved")
[1] "saved"
contrast_list <- c("SH3GL2-KO")
overlap_genes <- get_specific_gene_overlap(filtered_DEP, contrast_list)
# Print the result
print("Unique to SH3GL2")
[1] "Unique to SH3GL2"
print(overlap_genes)
 [1] "AIP"      "GTPBP1"   "MGRN1"    "CNTN5"    "KBTBD11"  "POLR2C"   "GLRX"     "ALDH7A1"  "KPNA1"    "TPD52"    "NCALD"    "GRM7"     "ETFDH"   
[14] "FRY"      "TBC1D9B"  "ZC3HAV1"  "ARHGAP12" "GDPD1"    "NUDT10"   "ITFG1"    "MICAL1"   "SH3KBP1"  "CHAMP1"   "LYSMD1"   "TSPAN18"  "OLFM1"   
[27] "DNAJC5"   "HEBP1"    "ABCB8"    "TMEM30A"  "GDE1"     "GPRC5B"   "EHD3"     "CACFD1"   "SEPTIN9"  "NFU1"     "GAB2"    
length(overlap_genes)
[1] 37
write.csv(overlap_genes,"/Users/rhalenathomas/Downloads/Move_Data/DarkGenomeResult/omics/OverlapLGeneLists/SH3GL2_DPE.csv")
print("saved")
[1] "saved"
contrast_list <- c("IP6K2-KO")
overlap_genes <- get_specific_gene_overlap(filtered_DEP, contrast_list)
# Print the result
print("Overlap of IP6K2")
[1] "Overlap of IP6K2"
print(overlap_genes)
 [1] "BRD4"    "PRKCA"   "PLCG1"   "FDFT1"   "MTIF2"   "DLG4"    "EPS8"    "RAPGEF1" "FKBP8"   "CYP51A1" "PRPF40B" "SCAI"    "SYNE1"   "FBXO41"  "SPOCK2" 
[16] "EVI5L"   "FYTTD1"  "CAMK2N2" "NT5DC2"  "SERINC1" "RPRM"    "TES"     "OGDHL"   "TDRKH"   "TMX2"   
length(overlap_genes)
[1] 25
write.csv(overlap_genes,"/Users/rhalenathomas/Downloads/Move_Data/DarkGenomeResult/omics/OverlapLGeneLists/IP6K2_DPE.csv")
print("saved")
[1] "saved"

Make one dataframe for expression lists

# look at each abundance dataframe

colnames(df.bright)
 [1] "Symbol"     "A53T.1"     "A53T.2"     "A53T.3"     "Control.1"  "Control.2"  "Control.3"  "GBA.KO.1"   "GBA.KO.2"   "GBA.KO.3"   "PINK1.KO.1"
[12] "PINK1.KO.2" "PINK1.KO.3" "PRKN.KO.1"  "PRKN.KO.2"  "PRKN.KO.3" 
colnames(df.dark)
 [1] "Symbol"      "Control.1"   "Control.2"   "Control.3"   "Control.4"   "IGSF9B.KO.1" "IGSF9B.KO.2" "INPP5F.KO.1" "INPP5F.KO.2" "INPP5F.KO.3"
[11] "IP6K2.KO.1"  "IP6K2.KO.2"  "IP6K2.KO.4"  "SH3GL2.KO.1" "SH3GL2.KO.2" "SH3GL2.KO.3"

Try some plots




df.long <- protein_zscore(data = df,
  proteins = lysome$`Gene name`, # Example protein names
  sample_patterns = c("Control","A53T","GBA.KO","PINK1.KO","PRKN.KO","INPP5F.KO","IGSF9B.KO" ,"SH3GL2.KO","IP6K2.KO"), group_means = TRUE) 
[1] "Sample columns selected: A53T.1, A53T.2, A53T.3, Control.1.x, Control.2.x, Control.3.x, GBA.KO.1, GBA.KO.2, GBA.KO.3, PINK1.KO.1, PINK1.KO.2, PINK1.KO.3, PRKN.KO.1, PRKN.KO.2, PRKN.KO.3, Control.1.y, Control.2.y, Control.3.y, Control.4, IGSF9B.KO.1, IGSF9B.KO.2, INPP5F.KO.1, INPP5F.KO.2, INPP5F.KO.3, IP6K2.KO.1, IP6K2.KO.2, IP6K2.KO.4, SH3GL2.KO.1, SH3GL2.KO.2, SH3GL2.KO.3"
  
max(df.long$Abundance, na.rm = TRUE)
[1] 4.035141
min(df.long$Abundance, na.rm = TRUE)
[1] -1.118153
# Example usage
heatmap_plot <- plot_clustered_protein_heatmap_zscore(
  data = df,
  proteins = lysome$`Gene name`, # Example protein names
  sample_patterns = c("Control", "A53T","GBA.KO","PINK1.KO","PRKN.KO","INPP5F.KO","IGSF9B.KO", "SH3GL2.KO","IP6K2.KO"),
  colors = c("snow", "lightgoldenrod1", "gold1", "darkorange1", "red2", "firebrick4"),
  scale_values = c(-1.5,-1,-0.5, 0, 2,4.5), # Adjust based on your data range
  group_means = TRUE, # Set to FALSE if you want individual samples
  cell_width = 20, # Control column width
  cell_height = 10 # Control row height
)
[1] "Sample columns selected: A53T.1, A53T.2, A53T.3, Control.1.x, Control.2.x, Control.3.x, GBA.KO.1, GBA.KO.2, GBA.KO.3, PINK1.KO.1, PINK1.KO.2, PINK1.KO.3, PRKN.KO.1, PRKN.KO.2, PRKN.KO.3, Control.1.y, Control.2.y, Control.3.y, Control.4, IGSF9B.KO.1, IGSF9B.KO.2, INPP5F.KO.1, INPP5F.KO.2, INPP5F.KO.3, IP6K2.KO.1, IP6K2.KO.2, IP6K2.KO.4, SH3GL2.KO.1, SH3GL2.KO.2, SH3GL2.KO.3"

# Example usage
heatmap_plot <- plot_clustered_protein_heatmap_zscore(
  data = df,
  proteins = lysome$`Gene name`,  # Example protein names
  sample_patterns = c("Control.", "A53T.","GBA.KO","PINK1.KO","PRKN.KO","INPP5F.KO","IGSF9B.KO", "SH3GL2.KO","IP6K2.KO"),
  colors = c("snow", "lightgoldenrod1", "gold1", "darkorange1", "red2", "firebrick4"),
  scale_values = c(-1,-0.5, 0, 2.5,5), # Adjust based on your data range
  group_means = FALSE, # Set to FALSE if you want individual samples
  cell_width = 20, # Control column width
  cell_height = 10 # Control row height
)
[1] "Sample columns selected: A53T.1, A53T.2, A53T.3, Control.1.x, Control.2.x, Control.3.x, GBA.KO.1, GBA.KO.2, GBA.KO.3, PINK1.KO.1, PINK1.KO.2, PINK1.KO.3, PRKN.KO.1, PRKN.KO.2, PRKN.KO.3, Control.1.y, Control.2.y, Control.3.y, Control.4, IGSF9B.KO.1, IGSF9B.KO.2, INPP5F.KO.1, INPP5F.KO.2, INPP5F.KO.3, IP6K2.KO.1, IP6K2.KO.2, IP6K2.KO.4, SH3GL2.KO.1, SH3GL2.KO.2, SH3GL2.KO.3"

Heat map of Logfold change

Same function but controling keeping the gene list order

Plot by dendrogram



# now plotted with function below

gene_list <- lysome$`Gene name`
contrast_list <- c("SNCA-A53T", "GBA-KO", "PINK1-KO", "PRKN-KO", "IGSF9B-KO","INPP5F-KO","SH3GL2-KO","IP6K2-KO")
p1 <- plot_logfold_change_heatmap_dendrogram(df_list_numeric, gene_list, contrast_list, remove_na_genes = TRUE, column_width = 1)
print(p1)



gene_list <- lysome$`Gene name`
contrast_list <- c("SNCA-A53T", "GBA-KO", "PINK1-KO", "PRKN-KO")
p2 <- plot_logfold_change_heatmap_dendrogram(df_list_numeric, gene_list, contrast_list, remove_na_genes = TRUE, column_width = 1)
print(p2)


gene_list <- lysome$`Gene name`
contrast_list <- c("IGSF9B-KO","INPP5F-KO","SH3GL2-KO","IP6K2-KO")
p3 <- plot_logfold_change_heatmap_dendrogram(df_list_numeric, gene_list, contrast_list, remove_na_genes = TRUE, column_width = 1)
print(p3)



gene_list <- lysome$`Gene name`
contrast_list <- c("SNCA-A53T", "GBA-KO", "PINK1-KO", "PRKN-KO","INPP5F-KO","SH3GL2-KO","IP6K2-KO")
p4 <- plot_logfold_change_heatmap_dendrogram(df_list_numeric, gene_list, contrast_list, remove_na_genes = TRUE, column_width = 1)
print(p4)

NA
NA


gene_list <- lysome$`Gene name`
contrast_list1 <- c("SNCA-A53T", "GBA-KO", "PINK1-KO", "PRKN-KO", "IGSF9B-KO","INPP5F-KO","SH3GL2-KO","IP6K2-KO")
contrast_list2 <- c("SNCA-A53T", "GBA-KO", "PINK1-KO", "PRKN-KO")
contrast_list3 <- c("IGSF9B-KO","INPP5F-KO","SH3GL2-KO","IP6K2-KO")
contrast_list4 <- c("SNCA-A53T", "GBA-KO", "PINK1-KO", "PRKN-KO","INPP5F-KO","SH3GL2-KO","IP6K2-KO")



pdf("/Users/rhalenathomas/Downloads/Move_Data/DarkGenomeResult/omics/HM_lysomeList_Log2FC_dendrogram.pdf", width = 6, height = 8)
plot_logfold_change_heatmap_dendrogram(df_list_numeric, gene_list, contrast_list1, remove_na_genes = TRUE, column_width = 1, title = "Log Fold Change Lysosome Genes")
plot_logfold_change_heatmap_dendrogram(df_list_numeric, gene_list, contrast_list1, remove_na_genes = TRUE, column_width = 1,title = "Log Fold Change Lysosome Genes")
plot_logfold_change_heatmap_dendrogram(df_list_numeric, gene_list, contrast_list3, remove_na_genes = TRUE, column_width = 1,title = "Log Fold Change Lysosome Genes")
plot_logfold_change_heatmap_dendrogram(df_list_numeric, gene_list, contrast_list4, remove_na_genes = TRUE, column_width = 1,title = "Log Fold Change Lysosome Genes")
dev.off()
null device 
          1 

get another gene list from Roxanne’s list

length(mito.genes)
[1] 1136

gene_list <- mito.genes[1:20]
#gene_list <- lysome$`Gene name`
contrast_list <- c("SNCA-A53T", "GBA-KO", "PINK1-KO", "PRKN-KO", "IGSF9B-KO","INPP5F-KO","SH3GL2-KO","IP6K2-KO")
p1 <- plot_logfold_change_heatmap_dendrogram(df_list_numeric, gene_list, contrast_list, remove_na_genes = TRUE, column_width = 12)
Warning: Values from `log2_ratio` are not uniquely identified; output will contain list-cols.
• Use `values_fn = list` to suppress this warning.
• Use `values_fn = {summary_fun}` to summarise duplicates.
• Use the following dplyr code to identify duplicates.
  {data} |>
  dplyr::summarise(n = dplyr::n(), .by = c(Symbol, Contrast)) |>
  dplyr::filter(n > 1L)
Error in `dplyr::mutate()`:
ℹ In argument: `across(-Symbol, as.numeric)`.
Caused by error in `across()`:
! Can't compute column `SNCA-A53T`.
Caused by error:
! 'list' object cannot be coerced to type 'double'
Backtrace:
  1. global plot_logfold_change_heatmap_dendrogram(...)
  4. dplyr:::mutate.data.frame(., across(-Symbol, as.numeric))
  5. dplyr:::mutate_cols(.data, dplyr_quosures(...), by)
  7. dplyr:::mutate_col(dots[[i]], data, mask, new_columns)
  9. mask$eval_all_mutate(quo)
 10. dplyr (local) eval()

New function to skip genes not found in df_list

print(mitocarta$Symbol[11:20])
 [1] "COX5A"   "ISCA2"   "PMPCB"   "UQCRFS1" "ATP5F1A" "OGDH"    "PDHB"    "UQCRC2"  "SDHD"    "MRPS35" 

This error seems to mean there are duplicate enteries for the same gene


plot_logfold_change_heatmap_dendrogram(df_list_numeric, gene_list = mitocarta$Symbol[1:10], contrast_list, 
                                       remove_na_genes = TRUE, column_width = 1)


plot_logfold_change_heatmap_dendrogram(df_list_numeric, gene_list = mitocarta$Symbol[10:20], contrast_list, 
                                       remove_na_genes = TRUE, column_width = 1)




plot_logfold_change_heatmap_dendrogram(df_list_numeric, gene_list = mitocarta$Symbol[11:60], contrast_list, 
                                       remove_na_genes = TRUE, column_width = 0.8)



plot_logfold_change_heatmap_dendrogram(df_list_numeric, gene_list = mitocarta$Symbol[1:20], contrast_list, 
                                       remove_na_genes = TRUE, column_width = 1)
Error in hclust(d, method = method) : 
  NA/NaN/Inf in foreign function call (arg 10)

We now need to remove problematic values

Force 0 to be the center of the scale

plot_logfold_change_heatmap_dendrogram <- function(df_list, gene_list, contrast_list, 
                                                   remove_na_genes = FALSE, column_width = 0.8, title = "Log Fold Change") {
  # Filter data to only include the specified genes and contrasts
  filtered_data <- df_list[contrast_list] %>%
    lapply(function(df) {
      df %>% 
        dplyr::filter(Symbol %in% gene_list) %>% 
        dplyr::select(Symbol, log2_ratio)
    }) %>% 
    dplyr::bind_rows(.id = "Contrast")
  
  # Ensure only genes in gene_list that are found in the filtered data are kept
  filtered_data <- filtered_data %>%
    dplyr::filter(Symbol %in% unique(filtered_data$Symbol))
  
  # Handle duplicates by summarizing (e.g., taking the mean)
  filtered_data <- filtered_data %>%
    dplyr::group_by(Symbol, Contrast) %>%
    dplyr::summarize(log2_ratio = mean(log2_ratio, na.rm = TRUE), .groups = 'drop')
  
  # Create a wide format matrix for heatmap plotting
  data_wide <- filtered_data %>%
    tidyr::pivot_wider(names_from = Contrast, values_from = log2_ratio) %>%
    dplyr::filter(Symbol %in% gene_list) %>% # Ensure only genes in gene_list are kept
    dplyr::mutate(dplyr::across(-Symbol, as.numeric))

  # Optionally remove genes that are NA across all contrasts
  if (remove_na_genes) {
    data_wide <- data_wide %>%
      dplyr::filter(rowSums(is.na(dplyr::select(., -Symbol))) < ncol(data_wide) - 1)
  }

  # Create a matrix for heatmap plotting
  mat <- as.matrix(data_wide %>% dplyr::select(-Symbol))
  rownames(mat) <- data_wide$Symbol
  
  # Check for NA, NaN, or Inf values in the matrix and remove any rows or columns that contain them
  mat <- mat[complete.cases(mat), ]  # Remove rows with NA/NaN/Inf values
  mat <- mat[, colSums(is.na(mat)) == 0]  # Remove columns with NA/NaN/Inf values
  
  # If after removing NA rows/columns the matrix becomes empty, return an informative error
  if (nrow(mat) == 0 || ncol(mat) == 0) {
    stop("The matrix is empty after removing rows/columns with NA/NaN/Inf values. No valid data to plot.")
  }
  
  # Determine the limits for the scale to be symmetric around zero
  max_val <- max(abs(mat), na.rm = TRUE)
  
  # Create the heatmap with dendrograms
  pheatmap::pheatmap(mat, 
                     cluster_rows = TRUE, 
                     cluster_cols = TRUE, 
                     scale = "none", 
                     color = colorRampPalette(c("blue", "white", "red"))(50),
                     breaks = seq(-max_val, max_val, length.out = 51), # Symmetric color scale
                     cellwidth = column_width * 10, # Adjust column width
                     show_rownames = TRUE,
                     show_colnames = TRUE,
                     main = title)
}

plot_logfold_change_heatmap_dendrogram(df_list_numeric, gene_list = mitocarta$Symbol, contrast_list, 
                                       remove_na_genes = TRUE, column_width = 1)

NA
NA
NA

Gene different heatmaps

gene_list <- mito.genes
#gene_list <- lysome$`Gene name`
contrast_list <- c("SNCA-A53T", "GBA-KO", "PINK1-KO", "PRKN-KO", "IGSF9B-KO","INPP5F-KO","SH3GL2-KO","IP6K2-KO")
p1 <- plot_logfold_change_heatmap_dendrogram(df_list_numeric, gene_list, contrast_list, remove_na_genes = TRUE, column_width = 1, title = "Log Fold Change Mitocarta Genes")
print(p1)



contrast_list <- c("SNCA-A53T", "GBA-KO", "PINK1-KO", "PRKN-KO")
p2 <- plot_logfold_change_heatmap_dendrogram(df_list_numeric, gene_list, contrast_list, remove_na_genes = TRUE, column_width = 1, title = "Log Fold Change Mitocarta Genes")
print(p2)


contrast_list <- c("IGSF9B-KO","INPP5F-KO","SH3GL2-KO","IP6K2-KO")
p3 <-plot_logfold_change_heatmap_dendrogram(df_list_numeric, gene_list, contrast_list, remove_na_genes = TRUE, column_width = 1, title = "Log Fold Change Mitocarta Genes")
print(p3)


contrast_list <- c("SNCA-A53T", "GBA-KO", "PINK1-KO", "PRKN-KO","INPP5F-KO","SH3GL2-KO","IP6K2-KO")
p4 <- plot_logfold_change_heatmap_dendrogram(df_list_numeric, gene_list, contrast_list, remove_na_genes = TRUE, column_width = 1, title = "Log Fold Change Mitocarta Genes")
print(p4)



contrast_list <- c("SNCA-A53T", "GBA-KO", "PINK1-KO", "PRKN-KO", "IGSF9B-KO","INPP5F-KO","SH3GL2-KO","IP6K2-KO")
gene_list <- mito.genes[1:100]
p1.1 <- plot_logfold_change_heatmap_dendrogram(df_list_numeric, gene_list, contrast_list, remove_na_genes = TRUE, column_width = 1, title = "Log Fold Change Mitocarta Genes 1-100")
p1.1 



contrast_list <- c("SNCA-A53T", "GBA-KO", "PINK1-KO", "PRKN-KO", "IGSF9B-KO","INPP5F-KO","SH3GL2-KO","IP6K2-KO")
gene_list <- mito.genes[101:200]
p1.2 <- plot_logfold_change_heatmap_dendrogram(df_list_numeric, gene_list, contrast_list, remove_na_genes = TRUE, column_width = 1, title = "Log Fold Change Mitocarta Genes 101-200")
p1.2


contrast_list <- c("SNCA-A53T", "GBA-KO", "PINK1-KO", "PRKN-KO", "IGSF9B-KO","INPP5F-KO","SH3GL2-KO","IP6K2-KO")
gene_list <- mito.genes[201:300]
p1.3 <- plot_logfold_change_heatmap_dendrogram(df_list_numeric, gene_list, contrast_list, remove_na_genes = TRUE, column_width = 1, title = "Log Fold Change Mitocarta Genes 201-300")
p1.3


contrast_list <- c("SNCA-A53T", "GBA-KO", "PINK1-KO", "PRKN-KO", "IGSF9B-KO","INPP5F-KO","SH3GL2-KO","IP6K2-KO")
gene_list <- mito.genes[301:400]
p1.4 <- plot_logfold_change_heatmap_dendrogram(df_list_numeric, gene_list, contrast_list, remove_na_genes = TRUE, column_width = 1, title = "Log Fold Change Mitocarta Genes 301-400")
p1.4


contrast_list <- c("SNCA-A53T", "GBA-KO", "PINK1-KO", "PRKN-KO", "IGSF9B-KO","INPP5F-KO","SH3GL2-KO","IP6K2-KO")
gene_list <- mito.genes[401:600]
p1.5 <- plot_logfold_change_heatmap_dendrogram(df_list_numeric, gene_list, contrast_list, remove_na_genes = TRUE, column_width = 1, title = "Log Fold Change Mitocarta Genes 401-600")
p1.5


contrast_list <- c("SNCA-A53T", "GBA-KO", "PINK1-KO", "PRKN-KO", "IGSF9B-KO","INPP5F-KO","SH3GL2-KO","IP6K2-KO")
gene_list <- mito.genes[601:800]
p1.6 <- plot_logfold_change_heatmap_dendrogram(df_list_numeric, gene_list, contrast_list, remove_na_genes = TRUE, column_width = 1, title = "Log Fold Change Mitocarta Genes 601-800")
p1.6


contrast_list <- c("SNCA-A53T", "GBA-KO", "PINK1-KO", "PRKN-KO", "IGSF9B-KO","INPP5F-KO","SH3GL2-KO","IP6K2-KO")
gene_list <- mito.genes[801:1136]
p1.7 <- plot_logfold_change_heatmap_dendrogram(df_list_numeric, gene_list, contrast_list, remove_na_genes = TRUE, column_width = 1, title = "Log Fold Change Mitocarta Genes 801-1136")
p1.7

NA
NA
NA

Save mitocharta plots

pdf("/Users/rhalenathomas/Downloads/Move_Data/DarkGenomeResult/omics/HM_Mitocharta_Log2FC_dendrogram.pdf")
p1
p1.1
p1.2
p1.3
p1.4
p1.5
p1.6
p1.7
p2
p3
p4
dev.off()
null device 
          1 

Read in another list of genes

head(pd.genes.list)

pd.genes <- pd.genes.list$Symbol

Look at the gene list for PD


gene_list <- pd.genes
#gene_list <- lysome$`Gene name`
contrast_list <- c("SNCA-A53T", "GBA-KO", "PINK1-KO", "PRKN-KO", "IGSF9B-KO","INPP5F-KO","SH3GL2-KO","IP6K2-KO")
p1 <- plot_logfold_change_heatmap_dendrogram(df_list_numeric, gene_list, contrast_list, remove_na_genes = TRUE, column_width = 1, title = "Log Fold Change PD Genes")
print(p1)



contrast_list <- c("SNCA-A53T", "GBA-KO", "PINK1-KO", "PRKN-KO")
p2 <- plot_logfold_change_heatmap_dendrogram(df_list_numeric, gene_list, contrast_list, remove_na_genes = TRUE, column_width = 1, title = "Log Fold Change PD Genes")
print(p2)


contrast_list <- c("IGSF9B-KO","INPP5F-KO","SH3GL2-KO","IP6K2-KO")
p3 <-plot_logfold_change_heatmap_dendrogram(df_list_numeric, gene_list, contrast_list, remove_na_genes = TRUE, column_width = 1, title = "Log Fold Change PD Genes")
print(p3)


contrast_list <- c("SNCA-A53T", "GBA-KO", "PINK1-KO", "PRKN-KO","INPP5F-KO","SH3GL2-KO","IP6K2-KO")
p4 <- plot_logfold_change_heatmap_dendrogram(df_list_numeric, gene_list, contrast_list, remove_na_genes = TRUE, column_width = 1, title = "Log Fold Change PD Genes")
print(p4)



contrast_list <- c("SNCA-A53T", "GBA-KO", "PINK1-KO", "PRKN-KO", "IGSF9B-KO","INPP5F-KO","SH3GL2-KO","IP6K2-KO")
gene_list <- pd.genes[1:50]
p1.1 <- plot_logfold_change_heatmap_dendrogram(df_list_numeric, gene_list, contrast_list, remove_na_genes = TRUE, column_width = 1, title = "Log Fold Change PD Genes 1-50")
p1.1 



contrast_list <- c("SNCA-A53T", "GBA-KO", "PINK1-KO", "PRKN-KO", "IGSF9B-KO","INPP5F-KO","SH3GL2-KO","IP6K2-KO")
gene_list <- pd.genes[50:100]
p1.2 <- plot_logfold_change_heatmap_dendrogram(df_list_numeric, gene_list, contrast_list, remove_na_genes = TRUE, column_width = 1, title = "Log Fold Change PD Genes 50-100")
p1.2


contrast_list <- c("SNCA-A53T", "GBA-KO", "PINK1-KO", "PRKN-KO", "IGSF9B-KO","INPP5F-KO","SH3GL2-KO","IP6K2-KO")
gene_list <- pd.genes[100:150]
p1.3 <- plot_logfold_change_heatmap_dendrogram(df_list_numeric, gene_list, contrast_list, remove_na_genes = TRUE, column_width = 1, title = "Log Fold Change PD Genes 100-150")
p1.3


contrast_list <- c("SNCA-A53T", "GBA-KO", "PINK1-KO", "PRKN-KO", "IGSF9B-KO","INPP5F-KO","SH3GL2-KO","IP6K2-KO")
gene_list <- pd.genes[150:200]
p1.4 <- plot_logfold_change_heatmap_dendrogram(df_list_numeric, gene_list, contrast_list, remove_na_genes = TRUE, column_width = 1, title = "Log Fold Change PD Genes 150-200")
p1.4


contrast_list <- c("SNCA-A53T", "GBA-KO", "PINK1-KO", "PRKN-KO", "IGSF9B-KO","INPP5F-KO","SH3GL2-KO","IP6K2-KO")
gene_list <- pd.genes[200:250]
p1.5 <- plot_logfold_change_heatmap_dendrogram(df_list_numeric, gene_list, contrast_list, remove_na_genes = TRUE, column_width = 1, title = "Log Fold Change PD Genes 200-250")
p1.5


contrast_list <- c("SNCA-A53T", "GBA-KO", "PINK1-KO", "PRKN-KO", "IGSF9B-KO","INPP5F-KO","SH3GL2-KO","IP6K2-KO")
gene_list <- pd.genes[250:300]
p1.6 <- plot_logfold_change_heatmap_dendrogram(df_list_numeric, gene_list, contrast_list, remove_na_genes = TRUE, column_width = 1, title = "Log Fold Change PD Genes 250-300")
p1.6


contrast_list <- c("SNCA-A53T", "GBA-KO", "PINK1-KO", "PRKN-KO", "IGSF9B-KO","INPP5F-KO","SH3GL2-KO","IP6K2-KO")
gene_list <- pd.genes[300:330]
p1.7 <- plot_logfold_change_heatmap_dendrogram(df_list_numeric, gene_list, contrast_list, remove_na_genes = TRUE, column_width = 1, title = "Log Fold Change PD Genes 300-330")
p1.7

NA
NA
pdf("/Users/rhalenathomas/Downloads/Move_Data/DarkGenomeResult/omics/HM_PD_genes_Log2FC_dendrogram.pdf")
p1
p1.1
p1.2
p1.3
p1.4
p1.5
p1.6
p1.7
p2
p3
p4
dev.off()
null device 
          1 

Read synapse list

synapse.genes.list <- read_excel("/Users/rhalenathomas/Downloads/Move_Data/DarkGenomeResult/List of genes for RNAseq or Proteomics/SYNAPSE_REDUCED_GENE_LIST.xlsx", col_names = FALSE)
New names:
• `` -> `...1`
head(synapse.genes.list)
colnames(synapse.genes.list) <- c("Symbol")
head(synapse.genes.list)
synapse.genes <- synapse.genes.list$Symbol
gene_list <- synapse.genes
#gene_list <- lysome$`Gene name`
contrast_list <- c("SNCA-A53T", "GBA-KO", "PINK1-KO", "PRKN-KO", "IGSF9B-KO","INPP5F-KO","SH3GL2-KO","IP6K2-KO")
p1 <- plot_logfold_change_heatmap_dendrogram(df_list_numeric, gene_list, contrast_list, remove_na_genes = TRUE, column_width = 1, title = "Log Fold Change Synapse Genes")
print(p1)



contrast_list <- c("SNCA-A53T", "GBA-KO", "PINK1-KO", "PRKN-KO")
p2 <- plot_logfold_change_heatmap_dendrogram(df_list_numeric, gene_list, contrast_list, remove_na_genes = TRUE, column_width = 1, title = "Log Fold Change Synapse Genes")
print(p2)


contrast_list <- c("IGSF9B-KO","INPP5F-KO","SH3GL2-KO","IP6K2-KO")
p3 <-plot_logfold_change_heatmap_dendrogram(df_list_numeric, gene_list, contrast_list, remove_na_genes = TRUE, column_width = 1, title = "Log Fold Change Synapse Genes")
print(p3)


contrast_list <- c("SNCA-A53T", "GBA-KO", "PINK1-KO", "PRKN-KO","INPP5F-KO","SH3GL2-KO","IP6K2-KO")
p4 <- plot_logfold_change_heatmap_dendrogram(df_list_numeric, gene_list, contrast_list, remove_na_genes = TRUE, column_width = 1, title = "Log Fold Change Synapse Genes")
print(p4)



contrast_list <- c("SNCA-A53T", "GBA-KO", "PINK1-KO", "PRKN-KO", "IGSF9B-KO","INPP5F-KO","SH3GL2-KO","IP6K2-KO")
gene_list <- synapse.genes[1:100]
p1.1 <- plot_logfold_change_heatmap_dendrogram(df_list_numeric, gene_list, contrast_list, remove_na_genes = TRUE, column_width = 1, title = "Log Fold Change Synapse Genes 1-100")
p1.1 



contrast_list <- c("SNCA-A53T", "GBA-KO", "PINK1-KO", "PRKN-KO", "IGSF9B-KO","INPP5F-KO","SH3GL2-KO","IP6K2-KO")
gene_list <- synapse.genes[100:200]
p1.2 <- plot_logfold_change_heatmap_dendrogram(df_list_numeric, gene_list, contrast_list, remove_na_genes = TRUE, column_width = 1, title = "Log Fold Change Synapse Genes 100-200")
p1.2


contrast_list <- c("SNCA-A53T", "GBA-KO", "PINK1-KO", "PRKN-KO", "IGSF9B-KO","INPP5F-KO","SH3GL2-KO","IP6K2-KO")
gene_list <- synapse.genes[200:300]
p1.3 <-plot_logfold_change_heatmap_dendrogram(df_list_numeric, gene_list, contrast_list, remove_na_genes = TRUE, column_width = 1, title = "Log Fold Change Synapse Genes 200-300")
p1.3


contrast_list <- c("SNCA-A53T", "GBA-KO", "PINK1-KO", "PRKN-KO", "IGSF9B-KO","INPP5F-KO","SH3GL2-KO","IP6K2-KO")
gene_list <- synapse.genes[300:400]
p1.4 <- plot_logfold_change_heatmap_dendrogram(df_list_numeric, gene_list, contrast_list, remove_na_genes = TRUE, column_width = 1, title = "Log Fold Change Synapse Genes 300-400")
p1.4


contrast_list <- c("SNCA-A53T", "GBA-KO", "PINK1-KO", "PRKN-KO", "IGSF9B-KO","INPP5F-KO","SH3GL2-KO","IP6K2-KO")
gene_list <- synapse.genes[400:500]
p1.5 <- plot_logfold_change_heatmap_dendrogram(df_list_numeric, gene_list, contrast_list, remove_na_genes = TRUE, column_width = 1, title = "Log Fold Change Synapse Genes 400-500")
p1.5


contrast_list <- c("SNCA-A53T", "GBA-KO", "PINK1-KO", "PRKN-KO", "IGSF9B-KO","INPP5F-KO","SH3GL2-KO","IP6K2-KO")
gene_list <- synapse.genes[500:594]
p1.6 <- plot_logfold_change_heatmap_dendrogram(df_list_numeric, gene_list, contrast_list, remove_na_genes = TRUE, column_width = 1, title = "Log Fold Change Synapse Genes 500-594")
p1.6

save the synaptic gene list

pdf("/Users/rhalenathomas/Downloads/Move_Data/DarkGenomeResult/omics/HM_Synpatic_genes_Log2FC_dendrogram.pdf")
p1
p1.1
p1.2
p1.3
p1.4
p1.5
p1.6
p2
p3
p4
dev.off()
null device 
          1 

GWAS PD

gwas.genes <- read.csv("/Users/rhalenathomas/Downloads/Move_Data/DarkGenomeResult/List of genes for RNAseq or Proteomics/ALL_PD_GWAS_GENELIST.csv")
head(gwas.genes)

All gwas genes

print(gene_list)
 [1] "ASXL3"        "BAG3"         "BIN3"         "BRIP1"        "BST1"         "C5orf24"      "CAB39L"       "CAMK2D"       "CASC16"       "CD19"        
[11] "CHRNB1"       "CLCN3"        "CRHR1"        "CRLS1"        "CTSB"         "DDX46"        "DGKQ"         "DLG2"         "DLST"         "DNAH17"      
[21] "DYRK1A"       "EHMT2"        "ELOVL7"       "FAM171A2"     "FAM47E"       "FAM47E-STBD1" "FAM49B"       "FBRSL1"       "FCGR2A"       "FGF11"       
[31] "GAK"          "GALC"         "GBA"          "GBAP1"        "GBF1"         "GCH1"         "GPNMB"        "GPR65"        "GRN"          "HIP1R"       
[41] "IGSF9B"       "INPP5F"       "IP6K2"        "ITGA8"        "ITPKB"        "KANSL1"       "KCNIP3"       "KCNS3"        "KPNA1"        "KRTCAP2"     
[51] "LCORL"        "LINC00693"    "LRRK2"        "MAP4K4"       "MAPT-AS1"     "MBNL2"        "MCCC1"        "MED12L"       "MIPOL1"       "MIR4308"     
[61] "MRVI1-AS1"    "MUC19"        "NOD2"         "NSF"          "NUCKS1"       "P2RY12"       "PAM"          "PGS1"         "PMVK"         "RAB7L1"      
[71] "RABEP2"       "RIT2"         "RNF141"       "RPS6KL1"      "SCARB2"       "SEMA4A"       "SETD1A"       "SH3GL2"       "SIPA1L2"      "SLC25A44"    
[81] "SLC44A4"      "SNCA"         "SPPL2B"       "SPPL2C"       "SPTSSB"       "STK39"        "SYT17"        "TBC1D5"       "TMEM163"      "TMEM175"     
[91] "TRIM40"       "UBAP2"        "UBTF"         "VAMP4"        "WNT3"         "ZBTB4"       
p1.4 <- plot_logfold_change_heatmap_dendrogram(df_list_numeric, gene_list, contrast_list, remove_na_genes = FALSE, column_width = 1, title = "Log Fold Change GWAS Genes with distance < 10000")
p1.4

pdf("/Users/rhalenathomas/Downloads/Move_Data/DarkGenomeResult/omics/HM_GWAS_genes_Log2FC_dendrogram.pdf")
p1
p1.1
p1.2
p1.3
p1.4
p2
p3
p4
dev.off()
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKCkRpZmZlcmVudGlhbCBhbmFseXNpcwoKCiMgUHJvdGVpbgpSZWFkIGluIGFsbCB0aGUgRFBFIGZpbGVzIGNhbGN1bGF0ZWQgYnkgSkYgVHJlbXBlIExhYiBvci9hbmQgIFRNVC1hbmFseXN0IGJ5IFJMCkZpbGVzIHNlcGFyYXRlZCBieSBnZW5vdHlwZS9pUFNDIGxpbmUgaW4gdGhlIHdvcmtib29rICJQcm9jZXNzRmlsZXNSZW5hbWVBY2Nlc3Npb24uUm1kIgpBbGwgZGF0YSBpcyBmcm9tIDYgd2Vla3MgREFOcyBmcm9tIGlQU0MgbGluZXMgaW4gQUlXMDAyLTAyIGJhY2tncm91bmQKQnJpZ2h0IGdlbm9tZSBhbmQgZGFyayBnZW5vbWUgd2hlcmUgcnVuIHNlcGFyYXRlbHkKCmBgYHtyfQojIHJlYWQgaW4gY3N2IGludG8gdG8gbWFrZSBhIGxpc3Qgb2YgZGF0YWZyYW1lcwoKIyBMb2FkIHJlcXVpcmVkIGxpYnJhcnkKbGlicmFyeShyZWFkcikKCiMgdGhlIHByb3RlaW4gREUgZmlsZXMgYXJlIGhlcmUKZm9sZGVyX3BhdGggPC0gIi9Vc2Vycy9yaGFsZW5hdGhvbWFzL0Rvd25sb2Fkcy9Nb3ZlX0RhdGEvRGFya0dlbm9tZVJlc3VsdC9EUEVfZmlsZXMvIgoKIyBMaXN0IGFsbCBDU1YgZmlsZXMgaW4gdGhlIGZvbGRlcgpjc3ZfZmlsZXMgPC0gbGlzdC5maWxlcyhwYXRoID0gZm9sZGVyX3BhdGgsIHBhdHRlcm4gPSAiXFwuY3N2JCIsIGZ1bGwubmFtZXMgPSBUUlVFKQoKIyBSZWFkIGFsbCBDU1YgZmlsZXMgaW50byBhIGxpc3Qgb2YgZGF0YWZyYW1lcywgc2tpcHBpbmcgdGhlIGZpcnN0IGNvbHVtbgpkZl9saXN0IDwtIGxhcHBseShjc3ZfZmlsZXMsIGZ1bmN0aW9uKGZpbGUpIHsKICByZWFkX2NzdihmaWxlLCBjb2xfdHlwZXMgPSBjb2xzKC5kZWZhdWx0ID0gIj8iLCBgLi4uMWAgPSBjb2xfc2tpcCgpKSkKfSkKCiMgT3B0aW9uYWxseSwgbmFtZSBlYWNoIGVsZW1lbnQgb2YgdGhlIGxpc3Qgd2l0aCB0aGUgcmVzcGVjdGl2ZSBmaWxlIG5hbWVzICh3aXRob3V0IHRoZSAuY3N2IGV4dGVuc2lvbikKbmFtZXMoZGZfbGlzdCkgPC0gdG9vbHM6OmZpbGVfcGF0aF9zYW5zX2V4dChiYXNlbmFtZShjc3ZfZmlsZXMpKQoKIyBQcmludCB0aGUgbmFtZXMgb2YgdGhlIGRhdGFmcmFtZXMKcHJpbnQobmFtZXMoZGZfbGlzdCkpCgojIHRlc3QgdGhhdCB0aGVzZSBhcmUgZGF0YWZyYW1lcwoKZGYuZ2JhIDwtIGRmX2xpc3QkYEdCQS1LT19Qcm90b21pY3NEaWZmZXJlbnRpYWxBYnVuZGFuY2VgCmhlYWQoZGYuZ2JhKQoKCmBgYApSZW5hbWUgdGhlIGxpc3QKYGBge3J9Cm5hbWVzKGRmX2xpc3QpIDwtIGMoIkdCQS1LTyIsIklHU0Y5Qi1LTyIsIklOUFA1Ri1LTyIsIklQNksyLUtPIiwiUElOSzEtS08iLCJQUktOLUtPIiwiU0gzR0wyLUtPIiwiU05DQS1BNTNUIikKCnByaW50KG5hbWVzKGRmX2xpc3QpKQpoZWFkKGRmX2xpc3QkYEdCQS1LT2ApCgpgYGAKCiMgVm9sY2FubyBwbG90cwpUaHJlc2hvbGRzOiBMb2cyIGFidW5kYW5jZSByYXRpbyA+IDAuNSBhbmQgcCB2YWx1ZSA8IDAuMDUKCmBgYHtyLCBmaWcuaGVpZ2h0PTR9CiNsaWJyYXJ5KEVuaGFuY2VkVm9sY2FubykKCgpwQTUzVCA8LSBFbmhhbmNlZFZvbGNhbm8oZGZfbGlzdCRgU05DQS1BNTNUYCwKICAgIGxhYiA9IGRmX2xpc3QkYFNOQ0EtQTUzVGAkU3ltYm9sLAogICAgeCA9ICdsb2cyX3JhdGlvJywKICAgIHkgPSAncC12YWx1ZScsCiAgICBwQ3V0b2ZmID0gMC4wNSwKICAgIEZDY3V0b2ZmID0gMC41LAogICAgY29sQWxwaGEgPSAwLjUsCiAgICBsYWJTaXplID0gNSwKICAgIHhsaW0gPSBjKC0zLDMpLAogICAgeWxpbSA9IGMoMCwgNyksCiAgICBkcmF3Q29ubmVjdG9ycyA9IEZBTFNFLAogICAgd2lkdGhDb25uZWN0b3JzID0gMC4xLAogICAgbWF4Lm92ZXJsYXBzID0gNDAsCiAgICBsZWdlbmRQb3NpdGlvbiA9ICJyaWdodCIsCiAgICB0aXRsZSA9ICJTTkNBLUE1M1QgdnMgQ29udHJvbCIsCiAgICBzdWJ0aXRsZSA9ICJEaWZmZXJlbnRpYWwgUHJvdGVpbiBBYnVuZGFuY2UiCiAgICkgICsgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgtMywgMywgYnkgPSAwLjUpKSArICMgQWRqdXN0IHRoZSB4LWF4aXMgYnJlYWtzIGFzIG5lZWRlZApzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCA3KSwgZXhwYW5kID0gYygwLCAwKSkgKyAgIyBSZW1vdmUgc3BhY2UgYmVsb3cgdGhlIHktYXhpcwogIGNvb3JkX2NhcnRlc2lhbih4bGltID0gYygtMywgMyksIHlsaW0gPSBjKDAsIDcpKSArICAjIEVuc3VyZSB0aGF0IHRoZSBwbG90IGRvZXMgbm90IGRpc3BsYXkgcG9pbnRzIGJleW9uZCB0aGlzIHJhbmdlCiB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpLCBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpKSAgIyBBZGp1c3QgeC1heGlzIGxhYmVsIHNpemUKCgoKcEdCQSA8LSBFbmhhbmNlZFZvbGNhbm8oZGZfbGlzdCRgR0JBLUtPYCwKICAgIGxhYiA9IGRmX2xpc3QkYEdCQS1LT2AkU3ltYm9sLAogICAgeCA9ICdsb2cyX3JhdGlvJywKICAgIHkgPSAncC12YWx1ZScsCiAgICBwQ3V0b2ZmID0gMC4wNSwKICAgIEZDY3V0b2ZmID0gMC41LAogICAgY29sQWxwaGEgPSAwLjUsCiAgICBsYWJTaXplID0gNSwKICAgIHhsaW0gPSBjKC0zLDMpLAogICAgeWxpbSA9IGMoMCwgNyksCiAgICBkcmF3Q29ubmVjdG9ycyA9IEZBTFNFLAogICAgd2lkdGhDb25uZWN0b3JzID0gMC4xLAogICAgbWF4Lm92ZXJsYXBzID0gNDAsCiAgICBsZWdlbmRQb3NpdGlvbiA9ICJyaWdodCIsCiAgICB0aXRsZSA9ICJHQkEtS08gdnMgQ29udHJvbCIsCiAgICBzdWJ0aXRsZSA9ICJEaWZmZXJlbnRpYWwgUHJvdGVpbiBBYnVuZGFuY2UiCiAgICkgICsgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgtNCwgNCwgYnkgPSAwLjUpKSArICMgQWRqdXN0IHRoZSB4LWF4aXMgYnJlYWtzIGFzIG5lZWRlZApzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCA3KSwgZXhwYW5kID0gYygwLCAwKSkgKyAgIyBSZW1vdmUgc3BhY2UgYmVsb3cgdGhlIHktYXhpcwogIGNvb3JkX2NhcnRlc2lhbih4bGltID0gYygtMywgMyksIHlsaW0gPSBjKDAsIDcpKSArICAjIEVuc3VyZSB0aGF0IHRoZSBwbG90IGRvZXMgbm90IGRpc3BsYXkgcG9pbnRzIGJleW9uZCB0aGlzIHJhbmdlCiB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpLCBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpKSAgIyBBZGp1c3QgeC1heGlzIGxhYmVsIHNpemUKCgoKcFBJTksxIDwtIEVuaGFuY2VkVm9sY2FubyhkZl9saXN0JGBQSU5LMS1LT2AsCiAgICBsYWIgPSBkZl9saXN0JGBQSU5LMS1LT2AkU3ltYm9sLAogICAgeCA9ICdsb2cyX3JhdGlvJywKICAgIHkgPSAncC12YWx1ZScsCiAgICBwQ3V0b2ZmID0gMC4wNSwKICAgIEZDY3V0b2ZmID0gMC41LAogICAgY29sQWxwaGEgPSAwLjUsCiAgICBsYWJTaXplID0gNSwKICAgIHhsaW0gPSBjKC00LDMpLAogICAgeWxpbSA9IGMoMCwgNyksCiAgICBkcmF3Q29ubmVjdG9ycyA9IEZBTFNFLAogICAgd2lkdGhDb25uZWN0b3JzID0gMC4xLAogICAgbWF4Lm92ZXJsYXBzID0gNDAsCiAgICBsZWdlbmRQb3NpdGlvbiA9ICJyaWdodCIsCiAgICB0aXRsZSA9ICJQSU5LMS1LTyB2cyBDb250cm9sIiwKICAgIHN1YnRpdGxlID0gIkRpZmZlcmVudGlhbCBQcm90ZWluIEFidW5kYW5jZSIKICAgKSArIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoLTQsIDQsIGJ5ID0gMC41KSkgKyAgIyBBZGp1c3QgdGhlIHgtYXhpcyBicmVha3MgYXMgbmVlZGVkCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgNyksIGV4cGFuZCA9IGMoMCwgMCkpICsgICMgUmVtb3ZlIHNwYWNlIGJlbG93IHRoZSB5LWF4aXMKICBjb29yZF9jYXJ0ZXNpYW4oeGxpbSA9IGMoLTQsIDMpLCB5bGltID0gYygwLCA3KSkgKyAjIEVuc3VyZSB0aGF0IHRoZSBwbG90IGRvZXMgbm90IGRpc3BsYXkgcG9pbnRzIGJleW9uZCB0aGlzIHJhbmdlCiB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpLCBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpKSAgIyBBZGp1c3QgeC1heGlzIGxhYmVsIHNpemUKCiMgUGxvdCBmb3IgUFJLTi1LTwpwUFJLTiA8LSBFbmhhbmNlZFZvbGNhbm8oZGZfbGlzdCRgUFJLTi1LT2AsCiAgICBsYWIgPSBkZl9saXN0JGBQUktOLUtPYCRTeW1ib2wsCiAgICB4ID0gJ2xvZzJfcmF0aW8nLAogICAgeSA9ICdwLXZhbHVlJywKICAgIHBDdXRvZmYgPSAwLjA1LAogICAgRkNjdXRvZmYgPSAwLjUsCiAgICBjb2xBbHBoYSA9IDAuNSwKICAgIGxhYlNpemUgPSA1LAogICAgeGxpbSA9IGMoLTUsNCksCiAgICB5bGltID0gYygwLCAxMC41KSwKICAgIGRyYXdDb25uZWN0b3JzID0gRkFMU0UsCiAgICB3aWR0aENvbm5lY3RvcnMgPSAwLjEsCiAgICBtYXgub3ZlcmxhcHMgPSA0MCwKICAgIGxlZ2VuZFBvc2l0aW9uID0gInJpZ2h0IiwKICAgIHRpdGxlID0gIlBSS04tS08gdnMgQ29udHJvbCIsCiAgICBzdWJ0aXRsZSA9ICJEaWZmZXJlbnRpYWwgUHJvdGVpbiBBYnVuZGFuY2UiCiAgICkgKyBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKC01LCA0LCBieSA9IDAuNSkpICsgICMgQWRqdXN0IHRoZSB4LWF4aXMgYnJlYWtzIGFzIG5lZWRlZAogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDEwLjUpLCBleHBhbmQgPSBjKDAsIDApKSArICAjIFJlbW92ZSBzcGFjZSBiZWxvdyB0aGUgeS1heGlzCiAgY29vcmRfY2FydGVzaWFuKHhsaW0gPSBjKC01LCA0KSwgeWxpbSA9IGMoMCwgMTAuNSkpICsgICMgRW5zdXJlIHRoYXQgdGhlIHBsb3QgZG9lcyBub3QgZGlzcGxheSBwb2ludHMgYmV5b25kIHRoaXMgcmFuZ2UKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpLCBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpKSAgIyBBZGp1c3QgeC1heGlzIGxhYmVsIHNpemUKCnBJR1NGOUIgPC0gRW5oYW5jZWRWb2xjYW5vKGRmX2xpc3QkYElHU0Y5Qi1LT2AsCiAgICBsYWIgPSBkZl9saXN0JGBJR1NGOUItS09gJFN5bWJvbCwKICAgIHggPSAnbG9nMl9yYXRpbycsCiAgICB5ID0gJ3AtdmFsdWUnLAogICAgcEN1dG9mZiA9IDAuMDUsCiAgICBGQ2N1dG9mZiA9IDAuNSwKICAgIGNvbEFscGhhID0gMC41LAogICAgbGFiU2l6ZSA9IDUsCiAgICB4bGltID0gYygtNCw1LjUpLAogICAgeWxpbSA9IGMoMCwgMTEpLAogICAgZHJhd0Nvbm5lY3RvcnMgPSBGQUxTRSwKICAgIHdpZHRoQ29ubmVjdG9ycyA9IDAuMSwKICAgIG1heC5vdmVybGFwcyA9IDQwLAogICAgbGVnZW5kUG9zaXRpb24gPSAicmlnaHQiLAogICAgdGl0bGUgPSAiSUdTRjlCLUtPIHZzIENvbnRyb2wiLAogICAgc3VidGl0bGUgPSAiRGlmZmVyZW50aWFsIFByb3RlaW4gQWJ1bmRhbmNlIgogICApICsgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgtNCwgNS41LCBieSA9IDAuNSkpICsgICMgQWRqdXN0IHRoZSB4LWF4aXMgYnJlYWtzIGFzIG5lZWRlZAogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDExKSwgZXhwYW5kID0gYygwLCAwKSkgKyAgIyBSZW1vdmUgc3BhY2UgYmVsb3cgdGhlIHktYXhpcwogIGNvb3JkX2NhcnRlc2lhbih4bGltID0gYygtNCwgNS41KSwgeWxpbSA9IGMoMCwgMTEpKSArICAjIEVuc3VyZSB0aGF0IHRoZSBwbG90IGRvZXMgbm90IGRpc3BsYXkgcG9pbnRzIGJleW9uZCB0aGlzIHJhbmdlCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSkgICMgQWRqdXN0IHgtYXhpcyBsYWJlbCBzaXplCgoKCnBJTlBQNUYgPC0gRW5oYW5jZWRWb2xjYW5vKGRmX2xpc3QkYElOUFA1Ri1LT2AsCiAgICBsYWIgPSBkZl9saXN0JGBJTlBQNUYtS09gJFN5bWJvbCwKICAgIHggPSAnbG9nMl9yYXRpbycsCiAgICB5ID0gJ3AtdmFsdWUnLAogICAgcEN1dG9mZiA9IDAuMDUsCiAgICBGQ2N1dG9mZiA9IDAuNSwKICAgIGNvbEFscGhhID0gMC41LAogICAgbGFiU2l6ZSA9IDUsCiAgICB4bGltID0gYygtMywzKSwKICAgIHlsaW0gPSBjKDAsIDEwLjUpLAogICAgZHJhd0Nvbm5lY3RvcnMgPSBGQUxTRSwKICAgIHdpZHRoQ29ubmVjdG9ycyA9IDAuMSwKICAgIG1heC5vdmVybGFwcyA9IDQwLAogICAgbGVnZW5kUG9zaXRpb24gPSAicmlnaHQiLAogICAgdGl0bGUgPSAiSU5QUDVGLUtPIHZzIENvbnRyb2wiLAogICAgc3VidGl0bGUgPSAiRGlmZmVyZW50aWFsIFByb3RlaW4gQWJ1bmRhbmNlIgogICApICsgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgtMywgMywgYnkgPSAwLjUpKSArICAjIEFkanVzdCB0aGUgeC1heGlzIGJyZWFrcyBhcyBuZWVkZWQKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAxMC41KSwgZXhwYW5kID0gYygwLCAwKSkgKyAgIyBSZW1vdmUgc3BhY2UgYmVsb3cgdGhlIHktYXhpcwogIGNvb3JkX2NhcnRlc2lhbih4bGltID0gYygtMywgMyksIHlsaW0gPSBjKDAsIDEwLjUpKSArICAjIEVuc3VyZSB0aGF0IHRoZSBwbG90IGRvZXMgbm90IGRpc3BsYXkgcG9pbnRzIGJleW9uZCB0aGlzIHJhbmdlCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSkgICMgQWRqdXN0IHgtYXhpcyBsYWJlbCBzaXplCgoKcElQNksyIDwtIEVuaGFuY2VkVm9sY2FubyhkZl9saXN0JGBJUDZLMi1LT2AsCiAgICBsYWIgPSBkZl9saXN0JGBJUDZLMi1LT2AkU3ltYm9sLAogICAgeCA9ICdsb2cyX3JhdGlvJywKICAgIHkgPSAncC12YWx1ZScsCiAgICBwQ3V0b2ZmID0gMC4wNSwKICAgIEZDY3V0b2ZmID0gMC41LAogICAgY29sQWxwaGEgPSAwLjUsCiAgICBsYWJTaXplID0gNSwKICAgIHhsaW0gPSBjKC0yLDUuMiksCiAgICB5bGltID0gYygwLCA4KSwKICAgIGRyYXdDb25uZWN0b3JzID0gRkFMU0UsCiAgICB3aWR0aENvbm5lY3RvcnMgPSAwLjEsCiAgICBtYXgub3ZlcmxhcHMgPSA0MCwKICAgIGxlZ2VuZFBvc2l0aW9uID0gInJpZ2h0IiwKICAgIHRpdGxlID0gIklQNksyLUtPIHZzIENvbnRyb2wiLAogICAgc3VidGl0bGUgPSAiRGlmZmVyZW50aWFsIFByb3RlaW4gQWJ1bmRhbmNlIgogICApICsgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgtMi41LCAyLCBieSA9IDAuNSkpICsgICMgQWRqdXN0IHRoZSB4LWF4aXMgYnJlYWtzIGFzIG5lZWRlZAogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDgpLCBleHBhbmQgPSBjKDAsIDApKSArICAjIFJlbW92ZSBzcGFjZSBiZWxvdyB0aGUgeS1heGlzCiAgY29vcmRfY2FydGVzaWFuKHhsaW0gPSBjKC0yLjUsIDIpLCB5bGltID0gYygwLCA4KSkgKyAgIyBFbnN1cmUgdGhhdCB0aGUgcGxvdCBkb2VzIG5vdCBkaXNwbGF5IHBvaW50cyBiZXlvbmQgdGhpcyByYW5nZQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCksIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCkpICAjIEFkanVzdCB4LWF4aXMgbGFiZWwgc2l6ZQoKCnBTSDNHTDIgPC0gRW5oYW5jZWRWb2xjYW5vKGRmX2xpc3QkYFNIM0dMMi1LT2AsCiAgICBsYWIgPSBkZl9saXN0JGBTSDNHTDItS09gJFN5bWJvbCwKICAgIHggPSAnbG9nMl9yYXRpbycsCiAgICB5ID0gJ3AtdmFsdWUnLAogICAgcEN1dG9mZiA9IDAuMDUsCiAgICBGQ2N1dG9mZiA9IDAuNSwKICAgIGNvbEFscGhhID0gMC41LAogICAgbGFiU2l6ZSA9IDUsCiAgICB4bGltID0gYygtMywyLjUpLAogICAgeWxpbSA9IGMoMCwgMTAuNSksCiAgICBkcmF3Q29ubmVjdG9ycyA9IEZBTFNFLAogICAgd2lkdGhDb25uZWN0b3JzID0gMC4xLAogICAgbWF4Lm92ZXJsYXBzID0gNDAsCiAgICBsZWdlbmRQb3NpdGlvbiA9ICJyaWdodCIsCiAgICB0aXRsZSA9ICJTSDNHTDItS08gdnMgQ29udHJvbCIsCiAgICBzdWJ0aXRsZSA9ICJEaWZmZXJlbnRpYWwgUHJvdGVpbiBBYnVuZGFuY2UiCiAgICkgKyBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKC0zLCAyLjUsIGJ5ID0gMC41KSkgKyAgIyBBZGp1c3QgdGhlIHgtYXhpcyBicmVha3MgYXMgbmVlZGVkCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgMTAuNSksIGV4cGFuZCA9IGMoMCwgMCkpICsgICMgUmVtb3ZlIHNwYWNlIGJlbG93IHRoZSB5LWF4aXMKICBjb29yZF9jYXJ0ZXNpYW4oeGxpbSA9IGMoLTMsIDIuNSksIHlsaW0gPSBjKDAsIDEwLjUpKSArICAjIEVuc3VyZSB0aGF0IHRoZSBwbG90IGRvZXMgbm90IGRpc3BsYXkgcG9pbnRzIGJleW9uZCB0aGlzIHJhbmdlCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSkgICMgQWRqdXN0IHgtYXhpcyBsYWJlbCBzaXplCgoKCgpwQTUzVApwR0JBCnBQSU5LMQpwUFJLTgpwSUdTRjlCCnBJTlBQNUYKcElQNksyCnBTSDNHTDIKCmBgYAoKTWFrZSBhIGZpbHRlcmVkIGxpc3Qgb2YgZGF0YWZyYW1lcyB3aXRoIHRoZSB0aHJlc2hvbGRzCgpgYGB7cn0KY29sbmFtZXMoZGZfbGlzdCRgR0JBLUtPYCkKYGBgCgoKCmBgYHtyfQojIHVzZSBmdW5jdGlvbiB0byBmaWx0ZXIgdGhlIGxpc3Qgb2YgZGF0YWZyYW1lcwojIHVwZGF0ZSBmdW5jdGlvbiB0byBtYXRjaCBjb2x1bW4gbmFtZXMKCiMgRnVuY3Rpb24gdG8gZmlsdGVyIERHRSByZXN1bHRzIGJhc2VkIG9uIGNyaXRlcmlhIHNpZ25sZSBER0UgZGF0YWZyYW1lIGZpbHRlciBmdW5jdGlvbgpmaWx0ZXJfZGdlX3Jlc3VsdHMgPC0gZnVuY3Rpb24oZGdlX3Jlc3VsdHMsIGxvZ0ZDX3RocmVzaG9sZCA9IE5VTEwsIGxvZ0ZDX2RpcmVjdGlvbiA9IE5VTEwsIHBfdGhyZXNob2xkID0gMC4wMSwgcF9jb2wgPSAicC12YWx1ZSIpIHsKICBpZiAoIWlzLm51bGwobG9nRkNfdGhyZXNob2xkKSkgewogICAgaWYgKGxvZ0ZDX2RpcmVjdGlvbiA9PSAicG9zaXRpdmUiKSB7CiAgICAgIGRnZV9yZXN1bHRzIDwtIGRnZV9yZXN1bHRzICU+JQogICAgICAgIGZpbHRlcihsb2cyX3JhdGlvID4gbG9nRkNfdGhyZXNob2xkKQogICAgfSBlbHNlIGlmIChsb2dGQ19kaXJlY3Rpb24gPT0gIm5lZ2F0aXZlIikgewogICAgICBkZ2VfcmVzdWx0cyA8LSBkZ2VfcmVzdWx0cyAlPiUKICAgICAgICBmaWx0ZXIobG9nMl9yYXRpbyA8IC1sb2dGQ190aHJlc2hvbGQpCiAgICB9IGVsc2UgaWYgKGxvZ0ZDX2RpcmVjdGlvbiA9PSAiYm90aCIpIHsKICAgICAgZGdlX3Jlc3VsdHMgPC0gZGdlX3Jlc3VsdHMgJT4lCiAgICAgICAgZmlsdGVyKGFicyhsb2cyX3JhdGlvKSA+IGxvZ0ZDX3RocmVzaG9sZCkKICAgIH0KICB9CiAgCiAgZGdlX3Jlc3VsdHNfZmlsdGVyZWQgPC0gZGdlX3Jlc3VsdHMgJT4lCiAgICBmaWx0ZXIoISFzeW0ocF9jb2wpIDwgcF90aHJlc2hvbGQpCiAgCiAgcmV0dXJuKGRnZV9yZXN1bHRzX2ZpbHRlcmVkKQp9CgojIEFwcGx5IGZpbHRlcmluZyB0byBER0UgbGlzdHMgLSB1c2VzIHRoZSBmdW5jdGlvbiBhYm92ZSB0byBmaWx0ZXIgZWFjaCBjZWxsIHR5cGUgbGlzdCBpbnNpZGUgZWFjaCBjb250cmFzdCBsaXN0CmZpbHRlcl9kZ2VfbGlzdHMgPC0gZnVuY3Rpb24oZGdlX2xpc3RzLCBsb2dGQ190aHJlc2hvbGQgPSAwLjI1LCBsb2dGQ19kaXJlY3Rpb24gPSAiYm90aCIsIHBfdGhyZXNob2xkID0gMC4wMSwgcF9jb2wgPSAicF92YWxfYWRqIikgewogIGRnZV9saXN0c19maWx0ZXJlZCA8LSBsYXBwbHkoZGdlX2xpc3RzLCBmdW5jdGlvbihkZ2VfbGlzdCkgewogICAgbGFwcGx5KGRnZV9saXN0LCBmdW5jdGlvbihkZ2VfZGYpIHsKICAgICAgZmlsdGVyZWRfZGYgPC0gZmlsdGVyX2RnZV9yZXN1bHRzKGRnZV9kZiwgbG9nRkNfdGhyZXNob2xkLCBsb2dGQ19kaXJlY3Rpb24sIHBfdGhyZXNob2xkLCBwX2NvbCkKICAgICAgcmV0dXJuKGZpbHRlcmVkX2RmKQogICAgfSkKICB9KQogIHJldHVybihkZ2VfbGlzdHNfZmlsdGVyZWQpCn0KCgoKCiMgRnVuY3Rpb24gdG8gY29udmVydCBzcGVjaWZpZWQgY29sdW1ucyB0byBudW1lcmljCmNvbnZlcnRfdG9fbnVtZXJpYyA8LSBmdW5jdGlvbihkZiwgY29scykgewogIGRmW2NvbHNdIDwtIGxhcHBseShkZltjb2xzXSwgYXMubnVtZXJpYykKICByZXR1cm4oZGYpCn0KCiMgQXBwbHkgY29udmVyc2lvbiB0byBlYWNoIGRhdGFmcmFtZSBpbiB0aGUgbGlzdApjb252ZXJ0X2xpc3RfY29sdW1ucyA8LSBmdW5jdGlvbihkZl9saXN0LCBjb2xzKSB7CiAgbGFwcGx5KGRmX2xpc3QsIGZ1bmN0aW9uKGRmKSB7CiAgICBjb252ZXJ0X3RvX251bWVyaWMoZGYsIGNvbHMpCiAgfSkKfQoKIyBDb2x1bW5zIHRvIGNvbnZlcnQKbnVtZXJpY19jb2xzIDwtIGMoInAtdmFsdWUiLCAibG9nMl9yYXRpbyIpCgojIENvbnZlcnQgY29sdW1ucyB0byBudW1lcmljIGluIGFsbCBkYXRhZnJhbWVzIGluIHRoZSBsaXN0CmRmX2xpc3RfbnVtZXJpYyA8LSBjb252ZXJ0X2xpc3RfY29sdW1ucyhkZl9saXN0LCBudW1lcmljX2NvbHMpCgojIEZvciBmaWx0ZXJpbmcgbGlzdHMgb2YgREdFIHJlc3VsdHMKZmlsdGVyZWRfREVQIDwtIGZpbHRlcl9kZ2VfbGlzdHMoZGZfbGlzdF9udW1lcmljLCBsb2dGQ190aHJlc2hvbGQgPSAwLjUsIGxvZ0ZDX2RpcmVjdGlvbiA9ICJib3RoIiwgcF90aHJlc2hvbGQgPSAwLjA1LCBwX2NvbCA9ICJwLXZhbHVlIikKCgpoZWFkKGRmX2xpc3QkYElHU0Y5Qi1LT2ApCmhlYWQoZGZfbGlzdF9udW1lcmljJGBJR1NGOUItS09gKQoKYGBgCgpgYGB7cn0KbGlicmFyeShkcGx5cikKCiMgRnVuY3Rpb24gdG8gZmlsdGVyIERHRSByZXN1bHRzIGJhc2VkIG9uIGNyaXRlcmlhCmZpbHRlcl9kZ2VfcmVzdWx0cyA8LSBmdW5jdGlvbihkZ2VfcmVzdWx0cywgbG9nRkNfdGhyZXNob2xkID0gTlVMTCwgbG9nRkNfZGlyZWN0aW9uID0gTlVMTCwgcF90aHJlc2hvbGQgPSAwLjAxLCBwX2NvbCA9ICJwLXZhbHVlIikgewogICMgRGVidWdnaW5nOiBQcmludCBjb2x1bW4gbmFtZXMgdG8gY2hlY2sgaWYgcF9jb2wgaXMgcHJlc2VudAogIHByaW50KHBhc3RlKCJDb2x1bW5zIGluIGRhdGFmcmFtZToiLCBwYXN0ZShjb2xuYW1lcyhkZ2VfcmVzdWx0cyksIGNvbGxhcHNlID0gIiwgIikpKQogIAogIGlmICghcF9jb2wgJWluJSBjb2xuYW1lcyhkZ2VfcmVzdWx0cykpIHsKICAgIHN0b3AocGFzdGUoIkNvbHVtbiIsIHBfY29sLCAibm90IGZvdW5kIGluIHRoZSBkYXRhZnJhbWUiKSkKICB9CiAgCiAgIyBFbnN1cmUgY29sdW1ucyBhcmUgbnVtZXJpYwogIHByaW50KHBhc3RlKCJDbGFzc2VzIG9mIGNvbHVtbnM6IiwgcGFzdGUoc2FwcGx5KGRnZV9yZXN1bHRzLCBjbGFzcyksIGNvbGxhcHNlID0gIiwgIikpKQogIAogICMgQXBwbHkgbG9nRkMgZmlsdGVyaW5nIGlmIHNwZWNpZmllZAogIGlmICghaXMubnVsbChsb2dGQ190aHJlc2hvbGQpKSB7CiAgICBpZiAobG9nRkNfZGlyZWN0aW9uID09ICJwb3NpdGl2ZSIpIHsKICAgICAgZGdlX3Jlc3VsdHMgPC0gZGdlX3Jlc3VsdHMgJT4lCiAgICAgICAgZmlsdGVyKGxvZzJfcmF0aW8gPiBsb2dGQ190aHJlc2hvbGQpCiAgICB9IGVsc2UgaWYgKGxvZ0ZDX2RpcmVjdGlvbiA9PSAibmVnYXRpdmUiKSB7CiAgICAgIGRnZV9yZXN1bHRzIDwtIGRnZV9yZXN1bHRzICU+JQogICAgICAgIGZpbHRlcihsb2cyX3JhdGlvIDwgLWxvZ0ZDX3RocmVzaG9sZCkKICAgIH0gZWxzZSBpZiAobG9nRkNfZGlyZWN0aW9uID09ICJib3RoIikgewogICAgICBkZ2VfcmVzdWx0cyA8LSBkZ2VfcmVzdWx0cyAlPiUKICAgICAgICBmaWx0ZXIoYWJzKGxvZzJfcmF0aW8pID4gbG9nRkNfdGhyZXNob2xkKQogICAgfQogIH0KICAKICAjIEFwcGx5IHAtdmFsdWUgZmlsdGVyaW5nCiAgZGdlX3Jlc3VsdHNfZmlsdGVyZWQgPC0gZGdlX3Jlc3VsdHMgJT4lCiAgICBmaWx0ZXIoISFzeW0ocF9jb2wpIDwgcF90aHJlc2hvbGQpCiAgCiAgcmV0dXJuKGRnZV9yZXN1bHRzX2ZpbHRlcmVkKQp9CgoKdGVzdCA8LSBmaWx0ZXJfZGdlX3Jlc3VsdHMoZGZfbGlzdCRgR0JBLUtPYCxsb2dGQ19kaXJlY3Rpb24gPSAiYm90aCIsIGxvZ0ZDX3RocmVzaG9sZCA9IDAuNSwgcF90aHJlc2hvbGQgPSAwLjA1LCBwX2NvbCA9ICJwLXZhbHVlIikKCiMgbm93IGFwcGx5IHRoZSBmaWx0ZXIgZnVuY3Rpb24gYWNyb3NzIGFsbCBkZiBpbiBvbmUgbGlzdAoKZmlsdGVyX2RnZV9saXN0cyA8LSBmdW5jdGlvbihkZ2VfbGlzdHMsIGxvZ0ZDX3RocmVzaG9sZCA9IDAuMjUsIGxvZ0ZDX2RpcmVjdGlvbiA9ICJib3RoIiwgcF90aHJlc2hvbGQgPSAwLjAxLCBwX2NvbCA9ICJwLXZhbHVlIikgewogICMgSXRlcmF0ZSBvdmVyIGVhY2ggZGF0YWZyYW1lIGluIHRoZSBsaXN0CiAgZGdlX2xpc3RzX2ZpbHRlcmVkIDwtIGxhcHBseShkZ2VfbGlzdHMsIGZ1bmN0aW9uKGRnZV9kZikgewogICAgIyBEZWJ1Z2dpbmc6IFByaW50IGNvbHVtbiBuYW1lcyBvZiB0aGUgZGF0YWZyYW1lIGJlaW5nIHByb2Nlc3NlZAogICAgcHJpbnQocGFzdGUoIlByb2Nlc3NpbmcgZGF0YWZyYW1lIHdpdGggY29sdW1uczoiLCBwYXN0ZShjb2xuYW1lcyhkZ2VfZGYpLCBjb2xsYXBzZSA9ICIsICIpKSkKICAgIAogICAgIyBBcHBseSB0aGUgZmlsdGVyIGZ1bmN0aW9uIHRvIGVhY2ggZGF0YWZyYW1lCiAgICBmaWx0ZXJlZF9kZiA8LSBmaWx0ZXJfZGdlX3Jlc3VsdHMoZGdlX2RmLCBsb2dGQ190aHJlc2hvbGQsIGxvZ0ZDX2RpcmVjdGlvbiwgcF90aHJlc2hvbGQsIHBfY29sKQogICAgCiAgICByZXR1cm4oZmlsdGVyZWRfZGYpCiAgfSkKICAKICByZXR1cm4oZGdlX2xpc3RzX2ZpbHRlcmVkKQp9CgojIHJ1biB0aGUgZmlsdGVyaW5nCmZpbHRlcmVkX0RFUCA8LSBmaWx0ZXJfZGdlX2xpc3RzKGRmX2xpc3QsIGxvZ0ZDX3RocmVzaG9sZCA9IDAuNSwgbG9nRkNfZGlyZWN0aW9uID0gImJvdGgiLCBwX3RocmVzaG9sZCA9IDAuMDUsIHBfY29sID0gInAtdmFsdWUiKQoKCgpgYGAKCkdldCBnZW5lIGNvdW50cwoKYGBge3J9CgojIGZ1bmN0aW9uIHRvIGNvdW50IHVwIGFuZCBkb3duIHJlZ3VsYXRlZCBQcm90ZWlucwpjb3VudF9yZWd1bGF0aW9ucyA8LSBmdW5jdGlvbihkZ2VfZGYpIHsKICAjIEVuc3VyZSBjb2x1bW5zIGFyZSBudW1lcmljCiAgZGdlX2RmJGxvZzJfcmF0aW8gPC0gYXMubnVtZXJpYyhkZ2VfZGYkbG9nMl9yYXRpbykKICAKICAjIENvdW50IHVwcmVndWxhdGVkIGFuZCBkb3ducmVndWxhdGVkIHByb3RlaW5zCiAgdXByZWd1bGF0ZWRfY291bnQgPC0gc3VtKGRnZV9kZiRsb2cyX3JhdGlvID4gMCwgbmEucm0gPSBUUlVFKQogIGRvd25yZWd1bGF0ZWRfY291bnQgPC0gc3VtKGRnZV9kZiRsb2cyX3JhdGlvIDwgMCwgbmEucm0gPSBUUlVFKQogIAogIHJldHVybihjKFVwcmVndWxhdGVkID0gdXByZWd1bGF0ZWRfY291bnQsIERvd25yZWd1bGF0ZWQgPSBkb3ducmVndWxhdGVkX2NvdW50KSkKfQoKc3VtbWFyaXplX3JlZ3VsYXRpb25zIDwtIGZ1bmN0aW9uKGRnZV9saXN0cykgewogICMgR2V0IG5hbWVzIG9mIHRoZSBkYXRhZnJhbWVzCiAgZGZfbmFtZXMgPC0gbmFtZXMoZGdlX2xpc3RzKQogIAogICMgQXBwbHkgdGhlIGNvdW50aW5nIGZ1bmN0aW9uIHRvIGVhY2ggZGF0YWZyYW1lIGFuZCBuYW1lIHRoZSByZXN1bHQKICBjb3VudHNfbGlzdCA8LSBsYXBwbHkoZGdlX2xpc3RzLCBmdW5jdGlvbihkZikgewogICAgY291bnRzIDwtIGNvdW50X3JlZ3VsYXRpb25zKGRmKQogICAgcmV0dXJuKGNvdW50cykKICB9KQogIAogICMgQ29udmVydCB0aGUgbGlzdCBvZiBjb3VudHMgaW50byBhIGRhdGFmcmFtZQogIHJlc3VsdF9kZiA8LSBkby5jYWxsKHJiaW5kLCBjb3VudHNfbGlzdCkKICAKICAjIFNldCB0aGUgcm93IG5hbWVzIHRvIHRoZSBuYW1lcyBvZiB0aGUgb3JpZ2luYWwgZGF0YWZyYW1lcwogIHJvd25hbWVzKHJlc3VsdF9kZikgPC0gZGZfbmFtZXMKICAKICByZXR1cm4ocmVzdWx0X2RmKQp9CgojIGFwcGx5IHRvIGZpbHRlcmVkIGxpc3QKcmVndWxhdGlvbl9zdW1tYXJ5IDwtIHN1bW1hcml6ZV9yZWd1bGF0aW9ucyhmaWx0ZXJlZF9ERVApCnByaW50KHJlZ3VsYXRpb25fc3VtbWFyeSkKCgoKYGBgCgoKCmBgYHtyfQpjb2xuYW1lcyhmaWx0ZXJlZF9ERVAkYFBJTksxLUtPYCkKCmBgYAoKRnVuY3Rpb24gdG8gZ2V0IHRoZSB0b3AgbiBnZW5lcyB1cCBhbmQgZG93bgoKYGBge3J9CiMgRnVuY3Rpb24gdG8gc2VsZWN0IHRvcCBuIHVwIGFuZCBkb3duIHJlZ3VsYXRlZCBnZW5lcwpzZWxlY3RfdG9wX2dlbmVzIDwtIGZ1bmN0aW9uKGRnZV9kZiwgbG9nRkNfY29sID0gImxvZzJfcmF0aW8iLCBzeW1ib2xfY29sID0gIlN5bWJvbCIsIG4gPSAxMCkgewogICMgRW5zdXJlIGxvZzJfcmF0aW8gY29sdW1uIGlzIG51bWVyaWMKICBkZ2VfZGZbW2xvZ0ZDX2NvbF1dIDwtIGFzLm51bWVyaWMoZGdlX2RmW1tsb2dGQ19jb2xdXSkKICAKICAjIFNvcnQgZGF0YWZyYW1lIGJ5IGxvZzJfcmF0aW8gdG8gZ2V0IHRvcCB1cHJlZ3VsYXRlZCBhbmQgZG93bnJlZ3VsYXRlZCBnZW5lcwogIHRvcF91cHJlZ3VsYXRlZCA8LSBkZ2VfZGYgJT4lCiAgICBhcnJhbmdlKGRlc2MoISFzeW0obG9nRkNfY29sKSkpICU+JQogICAgaGVhZChuKSAlPiUKICAgIHB1bGwoISFzeW0oc3ltYm9sX2NvbCkpCiAgCiAgdG9wX2Rvd25yZWd1bGF0ZWQgPC0gZGdlX2RmICU+JQogICAgYXJyYW5nZSghIXN5bShsb2dGQ19jb2wpKSAlPiUKICAgIGhlYWQobikgJT4lCiAgICBwdWxsKCEhc3ltKHN5bWJvbF9jb2wpKQogIAogICMgQ29tYmluZSB1cHJlZ3VsYXRlZCBhbmQgZG93bnJlZ3VsYXRlZCBnZW5lcyBpbnRvIGEgc2luZ2xlIHZlY3RvcgogIHRvcF9nZW5lcyA8LSBjKHRvcF91cHJlZ3VsYXRlZCwgdG9wX2Rvd25yZWd1bGF0ZWQpCiAgCiAgcmV0dXJuKHRvcF9nZW5lcykKfQoKIyBFeGFtcGxlIHVzYWdlCnRvcF9nZW5lcyA8LSBzZWxlY3RfdG9wX2dlbmVzKGZpbHRlcmVkX0RFUCRgUElOSzEtS09gLCBuID0gMTApCnByaW50KHRvcF9nZW5lcykKCgoKYGBgCgpgYGB7cn0KIyBGdW5jdGlvbiB0byBzZWxlY3QgdG9wIG4gdXAgYW5kIGRvd24gcmVndWxhdGVkIGdlbmVzCnNlbGVjdF90b3BfZ2VuZXMgPC0gZnVuY3Rpb24oZGdlX2RmLCBsb2dGQ19jb2wgPSAibG9nMl9yYXRpbyIsIHN5bWJvbF9jb2wgPSAiU3ltYm9sIiwgbiA9IDEwKSB7CiAgIyBFbnN1cmUgbG9nMl9yYXRpbyBjb2x1bW4gaXMgbnVtZXJpYwogIGRnZV9kZltbbG9nRkNfY29sXV0gPC0gYXMubnVtZXJpYyhkZ2VfZGZbW2xvZ0ZDX2NvbF1dKQogIAogICMgU29ydCBkYXRhZnJhbWUgYnkgbG9nMl9yYXRpbyB0byBnZXQgdG9wIHVwcmVndWxhdGVkIGdlbmVzCiAgdG9wX3VwcmVndWxhdGVkIDwtIGRnZV9kZiAlPiUKICAgIGFycmFuZ2UoZGVzYyghIXN5bShsb2dGQ19jb2wpKSkgJT4lCiAgICBoZWFkKG4pICU+JQogICAgcHVsbCghIXN5bShzeW1ib2xfY29sKSkKICAKICAjIFNvcnQgZGF0YWZyYW1lIGJ5IGxvZzJfcmF0aW8gdG8gZ2V0IHRvcCBkb3ducmVndWxhdGVkIGdlbmVzCiAgdG9wX2Rvd25yZWd1bGF0ZWQgPC0gZGdlX2RmICU+JQogICAgYXJyYW5nZSghIXN5bShsb2dGQ19jb2wpKSAlPiUKICAgIGhlYWQobikgJT4lCiAgICBwdWxsKCEhc3ltKHN5bWJvbF9jb2wpKQogIAogICMgQ29tYmluZSB1cHJlZ3VsYXRlZCBhbmQgZG93bnJlZ3VsYXRlZCBnZW5lcyBpbnRvIGEgc2luZ2xlIHZlY3RvcgogICMgVXByZWd1bGF0ZWQgZmlyc3QsIGZvbGxvd2VkIGJ5IGRvd25yZWd1bGF0ZWQKICB0b3BfZ2VuZXMgPC0gYyh0b3BfdXByZWd1bGF0ZWQsIHRvcF9kb3ducmVndWxhdGVkKQogIAogIHJldHVybih0b3BfZ2VuZXMpCn0KCiMgRXhhbXBsZSB1c2FnZQp0b3BfZ2VuZXMgPC0gc2VsZWN0X3RvcF9nZW5lcyhmaWx0ZXJlZF9ERVAkYFBJTksxLUtPYCwgbiA9IDUpCnByaW50KHRvcF9nZW5lcykKCmBgYApgYGB7cn0KCmRmLnBpbmsxIDwtIGZpbHRlcmVkX0RFUCRgUElOSzEtS09gCgoKYGBgCgoKCgoKUGxvdCBhIGhlYXRtYXAgb2YgdGhlIHRvcCB1cCBhbmQgZG93biBnZW5lcwoKCmBgYHtyfQoKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHRpZHlyKQoKIyBGdW5jdGlvbiB0byBwbG90IGhlYXRtYXAgb2YgcmVsYXRpdmUgYWJ1bmRhbmNlCnBsb3RfcHJvdGVpbl9oZWF0bWFwIDwtIGZ1bmN0aW9uKGRhdGEsIHByb3RlaW5zLCBzYW1wbGVfcGF0dGVybnMsIG5hX2NvbG9yID0gImdyZXkiKSB7CiAgIyBGaWx0ZXIgdGhlIGRhdGEgZm9yIHNlbGVjdGVkIHByb3RlaW5zCiAgZGF0YV9maWx0ZXJlZCA8LSBkYXRhICU+JQogICAgZmlsdGVyKFN5bWJvbCAlaW4lIHByb3RlaW5zKQoKICAjIElkZW50aWZ5IHNhbXBsZSBjb2x1bW5zIG1hdGNoaW5nIHBhdHRlcm5zCiAgc2FtcGxlX2NvbHVtbnMgPC0gY29sbmFtZXMoZGF0YV9maWx0ZXJlZClbc2FwcGx5KGNvbG5hbWVzKGRhdGFfZmlsdGVyZWQpLCBmdW5jdGlvbihjb2xfbmFtZSkgewogICAgYW55KHNhcHBseShzYW1wbGVfcGF0dGVybnMsIGZ1bmN0aW9uKHApIGdyZXBsKHAsIGNvbF9uYW1lKSkpCiAgfSldCgogICMgRGVidWc6IENoZWNrIGNvbnRlbnRzIG9mIHNhbXBsZV9jb2x1bW5zCiAgcHJpbnQocGFzdGUoIlNhbXBsZSBjb2x1bW5zIHNlbGVjdGVkOiIsIHBhc3RlKHNhbXBsZV9jb2x1bW5zLCBjb2xsYXBzZSA9ICIsICIpKSkKCiAgIyBDaGVjayBpZiBzYW1wbGVfY29sdW1ucyBoYXMgdmFsaWQgZW50cmllcwogIGlmIChsZW5ndGgoc2FtcGxlX2NvbHVtbnMpID09IDApIHsKICAgIHN0b3AoIk5vIHNhbXBsZSBjb2x1bW5zIG1hdGNoZWQgdGhlIHBhdHRlcm5zIHByb3ZpZGVkLiIpCiAgfQoKICAjIFNlbGVjdCBvbmx5IGNvbHVtbnMgbWF0Y2hpbmcgc2FtcGxlIHBhdHRlcm5zIGFuZCB0aGUgU3ltYm9sIGNvbHVtbgogIGRhdGFfZmlsdGVyZWQgPC0gZGF0YV9maWx0ZXJlZCAlPiUKICAgIGRwbHlyOjpzZWxlY3QoU3ltYm9sLCBhbGxfb2Yoc2FtcGxlX2NvbHVtbnMpKSAgIyBFeHBsaWNpdGx5IHVzZSBkcGx5cjo6c2VsZWN0CgogICMgUmVtb3ZlIHJvd3Mgd2hlcmUgYWxsIHZhbHVlcyBhcmUgTkEgKGV4Y2x1ZGluZyB0aGUgU3ltYm9sIGNvbHVtbikKICBkYXRhX2ZpbHRlcmVkIDwtIGRhdGFfZmlsdGVyZWQgJT4lCiAgICBmaWx0ZXIocm93U3Vtcyhpcy5uYShkcGx5cjo6c2VsZWN0KC4sIC1TeW1ib2wpKSkgPCBsZW5ndGgoc2FtcGxlX2NvbHVtbnMpKQoKICAjIFJlc2hhcGUgZGF0YSBmb3IgZ2dwbG90CiAgZGF0YV9sb25nIDwtIGRhdGFfZmlsdGVyZWQgJT4lCiAgICBwaXZvdF9sb25nZXIoCiAgICAgIGNvbHMgPSAtU3ltYm9sLCAKICAgICAgbmFtZXNfdG8gPSAiU2FtcGxlIiwgCiAgICAgIHZhbHVlc190byA9ICJBYnVuZGFuY2UiCiAgICApCgogICMgQ3JlYXRlIHRoZSBoZWF0bWFwCiAgaGVhdG1hcF9wbG90IDwtIGdncGxvdChkYXRhX2xvbmcsIGFlcyh4ID0gU2FtcGxlLCB5ID0gU3ltYm9sLCBmaWxsID0gQWJ1bmRhbmNlKSkgKwogICAgZ2VvbV90aWxlKGNvbG9yID0gIndoaXRlIikgKwogICAgc2NhbGVfZmlsbF9ncmFkaWVudDIobG93ID0gImJsdWUiLCBtaWQgPSBuYV9jb2xvciwgaGlnaCA9ICJyZWQiLCBuYS52YWx1ZSA9IG5hX2NvbG9yLCBtaWRwb2ludCA9IG1lZGlhbihkYXRhX2xvbmckQWJ1bmRhbmNlLCBuYS5ybSA9IFRSVUUpKSArCiAgICB0aGVtZV9taW5pbWFsKCkgKwogICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkgKwogICAgbGFicyh0aXRsZSA9ICJQcm90ZWluIEFidW5kYW5jZSBIZWF0bWFwIiwgeCA9ICJTYW1wbGVzIiwgeSA9ICJQcm90ZWlucyIpCiAgCiAgcmV0dXJuKGhlYXRtYXBfcGxvdCkKfQoKCgoKYGBgCgoKClBsb3QgY29udHJvbCBhbmQgSVBTQyBsaW5lIGZvciBlYWNoIGxpc3QgCgpgYGB7cn0KCmFidW5kYW5jZS5icmlnaHQgPC0gcmVhZC5jc3YoIi9Vc2Vycy9yaGFsZW5hdGhvbWFzL0Rvd25sb2Fkcy9Nb3ZlX0RhdGEvRGFya0dlbm9tZVJlc3VsdC9Qcm90b21pY3NOb3JtR2VuZUFidW5kYW5jZV9icmlnaHQuY3N2IikKCmNvbG5hbWVzKGFidW5kYW5jZS5icmlnaHQpCgpkZiA8LSBhYnVuZGFuY2UuYnJpZ2h0WywgYygzLDU6MTYsMTg6MjApXQoKZGYuYnJpZ2h0IDwtIGFidW5kYW5jZS5icmlnaHRbLCBjKDMsNToxNiwxODoyMCldCiMgRXhhbXBsZSB1c2FnZQojIEFzc3VtaW5nICdkZicgaXMgeW91ciBkYXRhZnJhbWUgd2l0aCByZWxhdGl2ZSBhYnVuZGFuY2UgZGF0YQpoZWF0bWFwX3Bsb3QgPC0gcGxvdF9wcm90ZWluX2hlYXRtYXAoCiAgZGF0YSA9IGRmLAogIHByb3RlaW5zID0gdG9wX2dlbmVzLCAjIEV4YW1wbGUgcHJvdGVpbiBuYW1lcwogIHNhbXBsZV9wYXR0ZXJucyA9IGMoIkNvbnRyb2wiLCAiUElOSzEuS08iKQopCgojIFByaW50IHRoZSBwbG90CnByaW50KGhlYXRtYXBfcGxvdCkKCmBgYAp6LXNjb3JlCgpgYGB7cn0KI2xpYnJhcnkoZ2dwbG90MikKI2xpYnJhcnkoZHBseXIpCiNsaWJyYXJ5KHRpZHlyKQoKI2RhdGEgPSBkZgojcHJvdGVpbnMgPSB0b3BfZ2VuZXMKI3NhbXBsZV9wYXR0ZXJucyA9ICBjKCJDb250cm9sIiwgIlBJTksxLktPIikKCiMgRnVuY3Rpb24gdG8gcGxvdCBoZWF0bWFwIG9mIHJlbGF0aXZlIGFidW5kYW5jZSB3aXRoIFotc2NvcmVzCnBsb3RfcHJvdGVpbl9oZWF0bWFwX3pzY29yZSA8LSBmdW5jdGlvbihkYXRhLCBwcm90ZWlucywgc2FtcGxlX3BhdHRlcm5zLCBuYV9jb2xvciA9ICJncmV5Iil7CiAgIyBGaWx0ZXIgdGhlIGRhdGEgZm9yIHNlbGVjdGVkIHByb3RlaW5zCiAgZGF0YV9maWx0ZXJlZCA8LSBkYXRhICU+JQogICAgZmlsdGVyKFN5bWJvbCAlaW4lIHByb3RlaW5zKQogIAogICMgU2V0IHRoZSBvcmRlciBvZiB0aGUgU3ltYm9sIGZhY3RvciBiYXNlZCBvbiB0aGUgaW5wdXQgdmVjdG9yICdwcm90ZWlucycKICBkYXRhX2ZpbHRlcmVkJFN5bWJvbCA8LSBmYWN0b3IoZGF0YV9maWx0ZXJlZCRTeW1ib2wsIGxldmVscyA9IHByb3RlaW5zKQoKICAjIElkZW50aWZ5IHNhbXBsZSBjb2x1bW5zIG1hdGNoaW5nIHBhdHRlcm5zCiAgc2FtcGxlX2NvbHVtbnMgPC0gY29sbmFtZXMoZGF0YV9maWx0ZXJlZClbc2FwcGx5KGNvbG5hbWVzKGRhdGFfZmlsdGVyZWQpLCBmdW5jdGlvbihjb2xfbmFtZSkgewogICAgYW55KHNhcHBseShzYW1wbGVfcGF0dGVybnMsIGZ1bmN0aW9uKHApIGdyZXBsKHAsIGNvbF9uYW1lKSkpCiAgfSldCgogICMgRGVidWc6IENoZWNrIGNvbnRlbnRzIG9mIHNhbXBsZV9jb2x1bW5zCiAgcHJpbnQocGFzdGUoIlNhbXBsZSBjb2x1bW5zIHNlbGVjdGVkOiIsIHBhc3RlKHNhbXBsZV9jb2x1bW5zLCBjb2xsYXBzZSA9ICIsICIpKSkKCiAgIyBDaGVjayBpZiBzYW1wbGVfY29sdW1ucyBoYXMgdmFsaWQgZW50cmllcwogIGlmIChsZW5ndGgoc2FtcGxlX2NvbHVtbnMpID09IDApIHsKICAgIHN0b3AoIk5vIHNhbXBsZSBjb2x1bW5zIG1hdGNoZWQgdGhlIHBhdHRlcm5zIHByb3ZpZGVkLiIpCiAgfQoKICAjIFNlbGVjdCBvbmx5IGNvbHVtbnMgbWF0Y2hpbmcgc2FtcGxlIHBhdHRlcm5zIGFuZCB0aGUgU3ltYm9sIGNvbHVtbgogIGRhdGFfZmlsdGVyZWQgPC0gZGF0YV9maWx0ZXJlZCAlPiUKICAgIGRwbHlyOjpzZWxlY3QoU3ltYm9sLCBhbGxfb2Yoc2FtcGxlX2NvbHVtbnMpKQoKICAjIFJlbW92ZSByb3dzIHdoZXJlIGFsbCB2YWx1ZXMgYXJlIE5BIChleGNsdWRpbmcgdGhlIFN5bWJvbCBjb2x1bW4pCiAgZGF0YV9maWx0ZXJlZCA8LSBkYXRhX2ZpbHRlcmVkICU+JQogICAgZmlsdGVyKHJvd1N1bXMoaXMubmEoZHBseXI6OnNlbGVjdCguLCAtU3ltYm9sKSkpIDwgbGVuZ3RoKHNhbXBsZV9jb2x1bW5zKSkKCiAgIyBDYWxjdWxhdGUgWi1zY29yZXMgZm9yIGVhY2ggcHJvdGVpbiBhY3Jvc3MgdGhlIHNlbGVjdGVkIHNhbXBsZXMKICBkYXRhX3pzY29yZSA8LSBkYXRhX2ZpbHRlcmVkICU+JQogICAgbXV0YXRlKGFjcm9zcyhhbGxfb2Yoc2FtcGxlX2NvbHVtbnMpLCB+IHNjYWxlKC4pWywgMV0sIC5uYW1lcyA9ICJ6X3tjb2x9IikpCiAgIyBSZXNoYXBlIGRhdGEgZm9yIGdncGxvdAogIGRhdGFfbG9uZyA8LSBkYXRhX3pzY29yZSAlPiUKICAgIHBpdm90X2xvbmdlcigKICAgICAgY29scyA9IHN0YXJ0c193aXRoKCJ6XyIpLCAKICAgICAgbmFtZXNfdG8gPSAiU2FtcGxlIiwgCiAgICAgIHZhbHVlc190byA9ICJBYnVuZGFuY2UiCiAgICApICU+JQogICAgbXV0YXRlKFNhbXBsZSA9IGdzdWIoInpfIiwgIiIsIFNhbXBsZSkpICAjIFJlbW92ZSAnel8nIHByZWZpeCBmb3IgY2xlYW4gc2FtcGxlIG5hbWVzCiAgIyBDcmVhdGUgdGhlIGhlYXRtYXAKICBoZWF0bWFwX3Bsb3QgPC0gZ2dwbG90KGRhdGFfbG9uZywgYWVzKHggPSBTYW1wbGUsIHkgPSBTeW1ib2wsIGZpbGwgPSBBYnVuZGFuY2UpKSArCiAgICBnZW9tX3RpbGUoY29sb3IgPSAid2hpdGUiKSArCiAgICBzY2FsZV9maWxsX2dyYWRpZW50bigKICAgICNjb2xvcnMgPSBjKCIjZmZmZmZmIiwgIiNmZmNjY2MiLCAiI2ZmNjY2NiIsICIjZmYzMzMzIiwiI2ZhMDUwNSIsICIjY2MwMDAwIiwiIzk5MDAwMCIpLAogICAgI2NvbG9ycyA9IGMoIiNmZGZlZjQiLCAiI0RBRjdBNiIsICIjRkZDMzAwIiwgIiNGRjU3MzMiLCIjZTcxZjA1IiwiIzRkMGIwMiIpLAogICAgY29sb3JzID0gYygic25vdyIsImxpZ2h0Z29sZGVucm9kMSIsImdvbGQxIiwiZGFya29yYW5nZTEiLCJyZWQyIiwiZmlyZWJyaWNrNCIpLAogICAgdmFsdWVzID0gc2NhbGVzOjpyZXNjYWxlKGMoLTAuNSwgLTAuMjUsIDAsIDEsMiwyLjUsMi43NSkpLAogICAgbmEudmFsdWUgPSBuYV9jb2xvciwKICAgIGd1aWRlID0gZ3VpZGVfY29sb3JiYXIoCiAgICAgIGJhcndpZHRoID0gMSwKICAgICAgYmFyaGVpZ2h0ID0gMTAsCiAgICAgIHRpdGxlLnBvc2l0aW9uID0gInRvcCIsCiAgICAgIHRpdGxlLmhqdXN0ID0gMC41CiAgICApKSArCiAgICB0aGVtZV9taW5pbWFsKCkgKwogICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkgKwogICAgbGFicyh0aXRsZSA9ICJQcm90ZWluIEFidW5kYW5jZSBIZWF0bWFwIChaLVNjb3JlKSIsIHggPSAiU2FtcGxlcyIsIHkgPSAiUHJvdGVpbnMiKQogIAogIHJldHVybihoZWF0bWFwX3Bsb3QpCn0KCiMgRXhhbXBsZSB1c2FnZQpoZWF0bWFwX3Bsb3QgPC0gcGxvdF9wcm90ZWluX2hlYXRtYXBfenNjb3JlKAogIGRhdGEgPSBkZiwKICBwcm90ZWlucyA9IHRvcF9nZW5lcywgIyBFeGFtcGxlIHByb3RlaW4gbmFtZXMKICBzYW1wbGVfcGF0dGVybnMgPSBjKCJDb250cm9sIiwgIlBJTksxLktPIikKKQoKIyBQcmludCB0aGUgcGxvdApwcmludChoZWF0bWFwX3Bsb3QpCgoKCgpgYGAKCgpBZGp1c3QgdGhlIGZ1bmN0aW9uCgpgYGB7cn0KCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShkcGx5cikKbGlicmFyeSh0aWR5cikKCiMgRnVuY3Rpb24gdG8gcGxvdCBoZWF0bWFwIG9mIHJlbGF0aXZlIGFidW5kYW5jZSB3aXRoIFotc2NvcmVzCnBsb3RfcHJvdGVpbl9oZWF0bWFwX3pzY29yZSA8LSBmdW5jdGlvbihkYXRhLCBwcm90ZWlucywgc2FtcGxlX3BhdHRlcm5zLCBjb2xvcnMsIHNjYWxlX3ZhbHVlcywgbmFfY29sb3IgPSAiZ3JleSIpIHsKICAjIEZpbHRlciB0aGUgZGF0YSBmb3Igc2VsZWN0ZWQgcHJvdGVpbnMKICBkYXRhX2ZpbHRlcmVkIDwtIGRhdGEgJT4lCiAgICBmaWx0ZXIoU3ltYm9sICVpbiUgcHJvdGVpbnMpCiAgCiAgIyBTZXQgdGhlIG9yZGVyIG9mIHRoZSBTeW1ib2wgZmFjdG9yIGJhc2VkIG9uIHRoZSBpbnB1dCB2ZWN0b3IgJ3Byb3RlaW5zJwogIGRhdGFfZmlsdGVyZWQkU3ltYm9sIDwtIGZhY3RvcihkYXRhX2ZpbHRlcmVkJFN5bWJvbCwgbGV2ZWxzID0gcHJvdGVpbnMpCgogICMgSWRlbnRpZnkgc2FtcGxlIGNvbHVtbnMgbWF0Y2hpbmcgcGF0dGVybnMKICBzYW1wbGVfY29sdW1ucyA8LSBjb2xuYW1lcyhkYXRhX2ZpbHRlcmVkKVtzYXBwbHkoY29sbmFtZXMoZGF0YV9maWx0ZXJlZCksIGZ1bmN0aW9uKGNvbF9uYW1lKSB7CiAgICBhbnkoc2FwcGx5KHNhbXBsZV9wYXR0ZXJucywgZnVuY3Rpb24ocCkgZ3JlcGwocCwgY29sX25hbWUpKSkKICB9KV0KCiAgIyBEZWJ1ZzogQ2hlY2sgY29udGVudHMgb2Ygc2FtcGxlX2NvbHVtbnMKICBwcmludChwYXN0ZSgiU2FtcGxlIGNvbHVtbnMgc2VsZWN0ZWQ6IiwgcGFzdGUoc2FtcGxlX2NvbHVtbnMsIGNvbGxhcHNlID0gIiwgIikpKQoKICAjIENoZWNrIGlmIHNhbXBsZV9jb2x1bW5zIGhhcyB2YWxpZCBlbnRyaWVzCiAgaWYgKGxlbmd0aChzYW1wbGVfY29sdW1ucykgPT0gMCkgewogICAgc3RvcCgiTm8gc2FtcGxlIGNvbHVtbnMgbWF0Y2hlZCB0aGUgcGF0dGVybnMgcHJvdmlkZWQuIikKICB9CgogICMgU2VsZWN0IG9ubHkgY29sdW1ucyBtYXRjaGluZyBzYW1wbGUgcGF0dGVybnMgYW5kIHRoZSBTeW1ib2wgY29sdW1uCiAgZGF0YV9maWx0ZXJlZCA8LSBkYXRhX2ZpbHRlcmVkICU+JQogICAgZHBseXI6OnNlbGVjdChTeW1ib2wsIGFsbF9vZihzYW1wbGVfY29sdW1ucykpCgogICMgUmVtb3ZlIHJvd3Mgd2hlcmUgYWxsIHZhbHVlcyBhcmUgTkEgKGV4Y2x1ZGluZyB0aGUgU3ltYm9sIGNvbHVtbikKICBkYXRhX2ZpbHRlcmVkIDwtIGRhdGFfZmlsdGVyZWQgJT4lCiAgICBmaWx0ZXIocm93U3Vtcyhpcy5uYShkcGx5cjo6c2VsZWN0KC4sIC1TeW1ib2wpKSkgPCBsZW5ndGgoc2FtcGxlX2NvbHVtbnMpKQoKICAjIENhbGN1bGF0ZSBaLXNjb3JlcyBmb3IgZWFjaCBwcm90ZWluIGFjcm9zcyB0aGUgc2VsZWN0ZWQgc2FtcGxlcwogIGRhdGFfenNjb3JlIDwtIGRhdGFfZmlsdGVyZWQgJT4lCiAgICBtdXRhdGUoYWNyb3NzKGFsbF9vZihzYW1wbGVfY29sdW1ucyksIH4gc2NhbGUoLilbLCAxXSwgLm5hbWVzID0gInpfe2NvbH0iKSkKCiAgIyBSZXNoYXBlIGRhdGEgZm9yIGdncGxvdAogIGRhdGFfbG9uZyA8LSBkYXRhX3pzY29yZSAlPiUKICAgIHBpdm90X2xvbmdlcigKICAgICAgY29scyA9IHN0YXJ0c193aXRoKCJ6XyIpLCAKICAgICAgbmFtZXNfdG8gPSAiU2FtcGxlIiwgCiAgICAgIHZhbHVlc190byA9ICJBYnVuZGFuY2UiCiAgICApICU+JQogICAgbXV0YXRlKFNhbXBsZSA9IGdzdWIoInpfIiwgIiIsIFNhbXBsZSkpICAjIFJlbW92ZSAnel8nIHByZWZpeCBmb3IgY2xlYW4gc2FtcGxlIG5hbWVzCgogICMgQ3JlYXRlIHRoZSBoZWF0bWFwCiAgaGVhdG1hcF9wbG90IDwtIGdncGxvdChkYXRhX2xvbmcsIGFlcyh4ID0gU2FtcGxlLCB5ID0gU3ltYm9sLCBmaWxsID0gQWJ1bmRhbmNlKSkgKwogICAgZ2VvbV90aWxlKGNvbG9yID0gIndoaXRlIikgKwogICAgc2NhbGVfZmlsbF9ncmFkaWVudG4oCiAgICAgIGNvbG9ycyA9IGNvbG9ycywKICAgICAgdmFsdWVzID0gc2NhbGVzOjpyZXNjYWxlKHNjYWxlX3ZhbHVlcyksCiAgICAgIG5hLnZhbHVlID0gbmFfY29sb3IsCiAgICAgIGd1aWRlID0gZ3VpZGVfY29sb3JiYXIoCiAgICAgICAgYmFyd2lkdGggPSAxLAogICAgICAgIGJhcmhlaWdodCA9IDEwLAogICAgICAgIHRpdGxlLnBvc2l0aW9uID0gInRvcCIsCiAgICAgICAgdGl0bGUuaGp1c3QgPSAwLjUKICAgICAgKQogICAgKSArCiAgICB0aGVtZV9taW5pbWFsKCkgKwogICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkgKwogICAgbGFicyh0aXRsZSA9ICJQcm90ZWluIEFidW5kYW5jZSBIZWF0bWFwIChaLVNjb3JlKSIsIHggPSAiU2FtcGxlcyIsIHkgPSAiUHJvdGVpbnMiKQogIAogIHJldHVybihoZWF0bWFwX3Bsb3QpCn0KCiMgRXhhbXBsZSB1c2FnZQpoZWF0bWFwX3Bsb3QgPC0gcGxvdF9wcm90ZWluX2hlYXRtYXBfenNjb3JlKAogIGRhdGEgPSBkZiwKICBwcm90ZWlucyA9IHRvcF9nZW5lcywgIyBFeGFtcGxlIHByb3RlaW4gbmFtZXMKICBzYW1wbGVfcGF0dGVybnMgPSBjKCJDb250cm9sIiwgIlBJTksxLktPIiksCiAgY29sb3JzID0gYygic25vdyIsICJsaWdodGdvbGRlbnJvZDEiLCAiZ29sZDEiLCAiZGFya29yYW5nZTEiLCAicmVkMiIsICJmaXJlYnJpY2s0IiksCiAgc2NhbGVfdmFsdWVzID0gYygtMi41LCAtMiwgLTEsIDAsIDEsIDIsIDIuNSkgIyBBZGp1c3QgYmFzZWQgb24geW91ciBkYXRhIHJhbmdlCikKCiMgUHJpbnQgdGhlIHBsb3QKcHJpbnQoaGVhdG1hcF9wbG90KQoKCmBgYAoKCmBgYHtyfQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkodGlkeXIpCgojIEZ1bmN0aW9uIHRvIHBsb3QgaGVhdG1hcCBvZiByZWxhdGl2ZSBhYnVuZGFuY2Ugd2l0aCBaLXNjb3JlcwpwbG90X3Byb3RlaW5faGVhdG1hcF96c2NvcmUgPC0gZnVuY3Rpb24oZGF0YSwgcHJvdGVpbnMsIHNhbXBsZV9wYXR0ZXJucywgY29sb3JzLCBzY2FsZV92YWx1ZXMsIG5hX2NvbG9yID0gImdyZXkiLCBncm91cF9tZWFucyA9IEZBTFNFKSB7CiAgIyBGaWx0ZXIgdGhlIGRhdGEgZm9yIHNlbGVjdGVkIHByb3RlaW5zCiAgZGF0YV9maWx0ZXJlZCA8LSBkYXRhICU+JQogICAgZmlsdGVyKFN5bWJvbCAlaW4lIHByb3RlaW5zKQogIAogICMgU2V0IHRoZSBvcmRlciBvZiB0aGUgU3ltYm9sIGZhY3RvciBiYXNlZCBvbiB0aGUgaW5wdXQgdmVjdG9yICdwcm90ZWlucycKICBkYXRhX2ZpbHRlcmVkJFN5bWJvbCA8LSBmYWN0b3IoZGF0YV9maWx0ZXJlZCRTeW1ib2wsIGxldmVscyA9IHByb3RlaW5zKQoKICAjIElkZW50aWZ5IHNhbXBsZSBjb2x1bW5zIG1hdGNoaW5nIHBhdHRlcm5zCiAgc2FtcGxlX2NvbHVtbnMgPC0gY29sbmFtZXMoZGF0YV9maWx0ZXJlZClbc2FwcGx5KGNvbG5hbWVzKGRhdGFfZmlsdGVyZWQpLCBmdW5jdGlvbihjb2xfbmFtZSkgewogICAgYW55KHNhcHBseShzYW1wbGVfcGF0dGVybnMsIGZ1bmN0aW9uKHApIGdyZXBsKHAsIGNvbF9uYW1lKSkpCiAgfSldCgogICMgRGVidWc6IENoZWNrIGNvbnRlbnRzIG9mIHNhbXBsZV9jb2x1bW5zCiAgcHJpbnQocGFzdGUoIlNhbXBsZSBjb2x1bW5zIHNlbGVjdGVkOiIsIHBhc3RlKHNhbXBsZV9jb2x1bW5zLCBjb2xsYXBzZSA9ICIsICIpKSkKCiAgIyBDaGVjayBpZiBzYW1wbGVfY29sdW1ucyBoYXMgdmFsaWQgZW50cmllcwogIGlmIChsZW5ndGgoc2FtcGxlX2NvbHVtbnMpID09IDApIHsKICAgIHN0b3AoIk5vIHNhbXBsZSBjb2x1bW5zIG1hdGNoZWQgdGhlIHBhdHRlcm5zIHByb3ZpZGVkLiIpCiAgfQoKICAjIFNlbGVjdCBvbmx5IGNvbHVtbnMgbWF0Y2hpbmcgc2FtcGxlIHBhdHRlcm5zIGFuZCB0aGUgU3ltYm9sIGNvbHVtbgogIGRhdGFfZmlsdGVyZWQgPC0gZGF0YV9maWx0ZXJlZCAlPiUKICAgIGRwbHlyOjpzZWxlY3QoU3ltYm9sLCBhbGxfb2Yoc2FtcGxlX2NvbHVtbnMpKQoKICAjIFJlbW92ZSByb3dzIHdoZXJlIGFsbCB2YWx1ZXMgYXJlIE5BIChleGNsdWRpbmcgdGhlIFN5bWJvbCBjb2x1bW4pCiAgZGF0YV9maWx0ZXJlZCA8LSBkYXRhX2ZpbHRlcmVkICU+JQogICAgZmlsdGVyKHJvd1N1bXMoaXMubmEoZHBseXI6OnNlbGVjdCguLCAtU3ltYm9sKSkpIDwgbGVuZ3RoKHNhbXBsZV9jb2x1bW5zKSkKCiAgaWYgKGdyb3VwX21lYW5zKSB7CiAgICAjIEdyb3VwIHNhbXBsZXMgYnkgdGhlIGJhc2UgbmFtZSBhbmQgY2FsY3VsYXRlIG1lYW4KICAgIHNhbXBsZV9iYXNlIDwtIGdzdWIoIlxcLlxcZCskIiwgIiIsIGNvbG5hbWVzKGRhdGFfZmlsdGVyZWQpWy0xXSkKICAgIGRhdGFfZ3JvdXBlZCA8LSBkYXRhX2ZpbHRlcmVkICU+JQogICAgICBwaXZvdF9sb25nZXIoY29scyA9IC1TeW1ib2wsIG5hbWVzX3RvID0gIlNhbXBsZSIsIHZhbHVlc190byA9ICJBYnVuZGFuY2UiKSAlPiUKICAgICAgbXV0YXRlKFNhbXBsZUJhc2UgPSBnc3ViKCJcXC5cXGQrJCIsICIiLCBTYW1wbGUpKSAlPiUKICAgICAgZ3JvdXBfYnkoU3ltYm9sLCBTYW1wbGVCYXNlKSAlPiUKICAgICAgc3VtbWFyaXplKEFidW5kYW5jZSA9IG1lYW4oQWJ1bmRhbmNlLCBuYS5ybSA9IFRSVUUpLCAuZ3JvdXBzID0gJ2Ryb3AnKSAlPiUKICAgICAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IFNhbXBsZUJhc2UsIHZhbHVlc19mcm9tID0gQWJ1bmRhbmNlKQoKICAgICMgQ2FsY3VsYXRlIFotc2NvcmVzCiAgICBkYXRhX3pzY29yZSA8LSBkYXRhX2dyb3VwZWQgJT4lCiAgICAgIG11dGF0ZShhY3Jvc3MoLVN5bWJvbCwgfiBzY2FsZSguKVssIDFdLCAubmFtZXMgPSAiel97Y29sfSIpKQoKICAgICMgUmVzaGFwZSBkYXRhIGZvciBnZ3Bsb3QKICAgIGRhdGFfbG9uZyA8LSBkYXRhX3pzY29yZSAlPiUKICAgICAgcGl2b3RfbG9uZ2VyKAogICAgICAgIGNvbHMgPSBzdGFydHNfd2l0aCgiel8iKSwgCiAgICAgICAgbmFtZXNfdG8gPSAiU2FtcGxlIiwgCiAgICAgICAgdmFsdWVzX3RvID0gIkFidW5kYW5jZSIKICAgICAgKSAlPiUKICAgICAgbXV0YXRlKFNhbXBsZSA9IGdzdWIoInpfIiwgIiIsIFNhbXBsZSkpICAjIFJlbW92ZSAnel8nIHByZWZpeCBmb3IgY2xlYW4gc2FtcGxlIG5hbWVzCiAgfSBlbHNlIHsKICAgICMgQ2FsY3VsYXRlIFotc2NvcmVzIGZvciBlYWNoIHByb3RlaW4gYWNyb3NzIHRoZSBzZWxlY3RlZCBzYW1wbGVzCiAgICBkYXRhX3pzY29yZSA8LSBkYXRhX2ZpbHRlcmVkICU+JQogICAgICBtdXRhdGUoYWNyb3NzKGFsbF9vZihzYW1wbGVfY29sdW1ucyksIH4gc2NhbGUoLilbLCAxXSwgLm5hbWVzID0gInpfe2NvbH0iKSkKCiAgICAjIFJlc2hhcGUgZGF0YSBmb3IgZ2dwbG90CiAgICBkYXRhX2xvbmcgPC0gZGF0YV96c2NvcmUgJT4lCiAgICAgIHBpdm90X2xvbmdlcigKICAgICAgICBjb2xzID0gc3RhcnRzX3dpdGgoInpfIiksIAogICAgICAgIG5hbWVzX3RvID0gIlNhbXBsZSIsIAogICAgICAgIHZhbHVlc190byA9ICJBYnVuZGFuY2UiCiAgICAgICkgJT4lCiAgICAgIG11dGF0ZShTYW1wbGUgPSBnc3ViKCJ6XyIsICIiLCBTYW1wbGUpKSAgIyBSZW1vdmUgJ3pfJyBwcmVmaXggZm9yIGNsZWFuIHNhbXBsZSBuYW1lcwogIH0KCiAgIyBDcmVhdGUgdGhlIGhlYXRtYXAKICBoZWF0bWFwX3Bsb3QgPC0gZ2dwbG90KGRhdGFfbG9uZywgYWVzKHggPSBTYW1wbGUsIHkgPSBTeW1ib2wsIGZpbGwgPSBBYnVuZGFuY2UpKSArCiAgICBnZW9tX3RpbGUoY29sb3IgPSAid2hpdGUiKSArCiAgICBzY2FsZV9maWxsX2dyYWRpZW50bigKICAgICAgY29sb3JzID0gY29sb3JzLAogICAgICB2YWx1ZXMgPSBzY2FsZXM6OnJlc2NhbGUoc2NhbGVfdmFsdWVzKSwKICAgICAgbmEudmFsdWUgPSBuYV9jb2xvciwKICAgICAgZ3VpZGUgPSBndWlkZV9jb2xvcmJhcigKICAgICAgICBiYXJ3aWR0aCA9IDEsCiAgICAgICAgYmFyaGVpZ2h0ID0gMTAsCiAgICAgICAgdGl0bGUucG9zaXRpb24gPSAidG9wIiwKICAgICAgICB0aXRsZS5oanVzdCA9IDAuNQogICAgICApCiAgICApICsKICAgIHRoZW1lX21pbmltYWwoKSArCiAgICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKSArCiAgICBsYWJzKHRpdGxlID0gIlByb3RlaW4gQWJ1bmRhbmNlIEhlYXRtYXAgKFotU2NvcmUpIiwgeCA9ICJTYW1wbGVzIiwgeSA9ICJQcm90ZWlucyIpCiAgCiAgcmV0dXJuKGhlYXRtYXBfcGxvdCkKfQoKIyBFeGFtcGxlIHVzYWdlCmhlYXRtYXBfcGxvdCA8LSBwbG90X3Byb3RlaW5faGVhdG1hcF96c2NvcmUoCiAgZGF0YSA9IGRmLAogIHByb3RlaW5zID0gdG9wX2dlbmVzLCAjIEV4YW1wbGUgcHJvdGVpbiBuYW1lcwogIHNhbXBsZV9wYXR0ZXJucyA9IGMoIkNvbnRyb2wiLCAiUElOSzEuS08iKSwKICBjb2xvcnMgPSBjKCJzbm93IiwgImxpZ2h0Z29sZGVucm9kMSIsICJnb2xkMSIsICJkYXJrb3JhbmdlMSIsICJyZWQyIiwgImZpcmVicmljazQiKSwKICBzY2FsZV92YWx1ZXMgPSBjKC0yLjUsIC0yLCAtMSwgMCwgMSwgMiwgMi41KSwgIyBBZGp1c3QgYmFzZWQgb24geW91ciBkYXRhIHJhbmdlCiAgZ3JvdXBfbWVhbnMgPSBUUlVFICMgU2V0IHRvIEZBTFNFIGlmIHlvdSB3YW50IGluZGl2aWR1YWwgc2FtcGxlcwopCgojIFByaW50IHRoZSBwbG90CnByaW50KGhlYXRtYXBfcGxvdCkKCgojIEV4YW1wbGUgdXNhZ2UKaGVhdG1hcF9wbG90IDwtIHBsb3RfcHJvdGVpbl9oZWF0bWFwX3pzY29yZSgKICBkYXRhID0gZGYsCiAgcHJvdGVpbnMgPSB0b3BfZ2VuZXMsICMgRXhhbXBsZSBwcm90ZWluIG5hbWVzCiAgc2FtcGxlX3BhdHRlcm5zID0gYygiQ29udHJvbCIsICJQSU5LMS5LTyIpLAogIGNvbG9ycyA9IGMoInNub3ciLCAibGlnaHRnb2xkZW5yb2QxIiwgImdvbGQxIiwgImRhcmtvcmFuZ2UxIiwgInJlZDIiLCAiZmlyZWJyaWNrNCIpLAogIHNjYWxlX3ZhbHVlcyA9IGMoLTIuNSwgLTIsIC0xLCAwLCAxLCAyLCAyLjUpLCAjIEFkanVzdCBiYXNlZCBvbiB5b3VyIGRhdGEgcmFuZ2UKICBncm91cF9tZWFucyA9IEZBTFNFICMgU2V0IHRvIEZBTFNFIGlmIHlvdSB3YW50IGluZGl2aWR1YWwgc2FtcGxlcwopCgojIFByaW50IHRoZSBwbG90CnByaW50KGhlYXRtYXBfcGxvdCkKCgpgYGAKCgpDb250cm9sIHdpZHRoCgpgYGB7cn0KbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHRpZHlyKQoKIyBGdW5jdGlvbiB0byBwbG90IGhlYXRtYXAgb2YgcmVsYXRpdmUgYWJ1bmRhbmNlIHdpdGggWi1zY29yZXMKcGxvdF9wcm90ZWluX2hlYXRtYXBfenNjb3JlIDwtIGZ1bmN0aW9uKGRhdGEsIHByb3RlaW5zLCBzYW1wbGVfcGF0dGVybnMsIGNvbG9ycywgc2NhbGVfdmFsdWVzLCBuYV9jb2xvciA9ICJncmV5IiwgZ3JvdXBfbWVhbnMgPSBGQUxTRSwgdGlsZV93aWR0aCA9IDAuOSkgewogICMgRmlsdGVyIHRoZSBkYXRhIGZvciBzZWxlY3RlZCBwcm90ZWlucwogIGRhdGFfZmlsdGVyZWQgPC0gZGF0YSAlPiUKICAgIGZpbHRlcihTeW1ib2wgJWluJSBwcm90ZWlucykKICAKICAjIFNldCB0aGUgb3JkZXIgb2YgdGhlIFN5bWJvbCBmYWN0b3IgYmFzZWQgb24gdGhlIGlucHV0IHZlY3RvciAncHJvdGVpbnMnCiAgZGF0YV9maWx0ZXJlZCRTeW1ib2wgPC0gZmFjdG9yKGRhdGFfZmlsdGVyZWQkU3ltYm9sLCBsZXZlbHMgPSBwcm90ZWlucykKCiAgIyBJZGVudGlmeSBzYW1wbGUgY29sdW1ucyBtYXRjaGluZyBwYXR0ZXJucwogIHNhbXBsZV9jb2x1bW5zIDwtIGNvbG5hbWVzKGRhdGFfZmlsdGVyZWQpW3NhcHBseShjb2xuYW1lcyhkYXRhX2ZpbHRlcmVkKSwgZnVuY3Rpb24oY29sX25hbWUpIHsKICAgIGFueShzYXBwbHkoc2FtcGxlX3BhdHRlcm5zLCBmdW5jdGlvbihwKSBncmVwbChwLCBjb2xfbmFtZSkpKQogIH0pXQoKICAjIERlYnVnOiBDaGVjayBjb250ZW50cyBvZiBzYW1wbGVfY29sdW1ucwogIHByaW50KHBhc3RlKCJTYW1wbGUgY29sdW1ucyBzZWxlY3RlZDoiLCBwYXN0ZShzYW1wbGVfY29sdW1ucywgY29sbGFwc2UgPSAiLCAiKSkpCgogICMgQ2hlY2sgaWYgc2FtcGxlX2NvbHVtbnMgaGFzIHZhbGlkIGVudHJpZXMKICBpZiAobGVuZ3RoKHNhbXBsZV9jb2x1bW5zKSA9PSAwKSB7CiAgICBzdG9wKCJObyBzYW1wbGUgY29sdW1ucyBtYXRjaGVkIHRoZSBwYXR0ZXJucyBwcm92aWRlZC4iKQogIH0KCiAgIyBTZWxlY3Qgb25seSBjb2x1bW5zIG1hdGNoaW5nIHNhbXBsZSBwYXR0ZXJucyBhbmQgdGhlIFN5bWJvbCBjb2x1bW4KICBkYXRhX2ZpbHRlcmVkIDwtIGRhdGFfZmlsdGVyZWQgJT4lCiAgICBkcGx5cjo6c2VsZWN0KFN5bWJvbCwgYWxsX29mKHNhbXBsZV9jb2x1bW5zKSkKCiAgIyBSZW1vdmUgcm93cyB3aGVyZSBhbGwgdmFsdWVzIGFyZSBOQSAoZXhjbHVkaW5nIHRoZSBTeW1ib2wgY29sdW1uKQogIGRhdGFfZmlsdGVyZWQgPC0gZGF0YV9maWx0ZXJlZCAlPiUKICAgIGZpbHRlcihyb3dTdW1zKGlzLm5hKGRwbHlyOjpzZWxlY3QoLiwgLVN5bWJvbCkpKSA8IGxlbmd0aChzYW1wbGVfY29sdW1ucykpCgogIGlmIChncm91cF9tZWFucykgewogICAgIyBHcm91cCBzYW1wbGVzIGJ5IHRoZSBiYXNlIG5hbWUgYW5kIGNhbGN1bGF0ZSBtZWFuCiAgICBzYW1wbGVfYmFzZSA8LSBnc3ViKCJcXC5cXGQrJCIsICIiLCBjb2xuYW1lcyhkYXRhX2ZpbHRlcmVkKVstMV0pCiAgICBkYXRhX2dyb3VwZWQgPC0gZGF0YV9maWx0ZXJlZCAlPiUKICAgICAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAtU3ltYm9sLCBuYW1lc190byA9ICJTYW1wbGUiLCB2YWx1ZXNfdG8gPSAiQWJ1bmRhbmNlIikgJT4lCiAgICAgIG11dGF0ZShTYW1wbGVCYXNlID0gZ3N1YigiXFwuXFxkKyQiLCAiIiwgU2FtcGxlKSkgJT4lCiAgICAgIGdyb3VwX2J5KFN5bWJvbCwgU2FtcGxlQmFzZSkgJT4lCiAgICAgIHN1bW1hcml6ZShBYnVuZGFuY2UgPSBtZWFuKEFidW5kYW5jZSwgbmEucm0gPSBUUlVFKSwgLmdyb3VwcyA9ICdkcm9wJykgJT4lCiAgICAgIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBTYW1wbGVCYXNlLCB2YWx1ZXNfZnJvbSA9IEFidW5kYW5jZSkKCiAgICAjIENhbGN1bGF0ZSBaLXNjb3JlcwogICAgZGF0YV96c2NvcmUgPC0gZGF0YV9ncm91cGVkICU+JQogICAgICBtdXRhdGUoYWNyb3NzKC1TeW1ib2wsIH4gc2NhbGUoLilbLCAxXSwgLm5hbWVzID0gInpfe2NvbH0iKSkKCiAgICAjIFJlc2hhcGUgZGF0YSBmb3IgZ2dwbG90CiAgICBkYXRhX2xvbmcgPC0gZGF0YV96c2NvcmUgJT4lCiAgICAgIHBpdm90X2xvbmdlcigKICAgICAgICBjb2xzID0gc3RhcnRzX3dpdGgoInpfIiksIAogICAgICAgIG5hbWVzX3RvID0gIlNhbXBsZSIsIAogICAgICAgIHZhbHVlc190byA9ICJBYnVuZGFuY2UiCiAgICAgICkgJT4lCiAgICAgIG11dGF0ZShTYW1wbGUgPSBnc3ViKCJ6XyIsICIiLCBTYW1wbGUpKSAgIyBSZW1vdmUgJ3pfJyBwcmVmaXggZm9yIGNsZWFuIHNhbXBsZSBuYW1lcwogIH0gZWxzZSB7CiAgICAjIENhbGN1bGF0ZSBaLXNjb3JlcyBmb3IgZWFjaCBwcm90ZWluIGFjcm9zcyB0aGUgc2VsZWN0ZWQgc2FtcGxlcwogICAgZGF0YV96c2NvcmUgPC0gZGF0YV9maWx0ZXJlZCAlPiUKICAgICAgbXV0YXRlKGFjcm9zcyhhbGxfb2Yoc2FtcGxlX2NvbHVtbnMpLCB+IHNjYWxlKC4pWywgMV0sIC5uYW1lcyA9ICJ6X3tjb2x9IikpCgogICAgIyBSZXNoYXBlIGRhdGEgZm9yIGdncGxvdAogICAgZGF0YV9sb25nIDwtIGRhdGFfenNjb3JlICU+JQogICAgICBwaXZvdF9sb25nZXIoCiAgICAgICAgY29scyA9IHN0YXJ0c193aXRoKCJ6XyIpLCAKICAgICAgICBuYW1lc190byA9ICJTYW1wbGUiLCAKICAgICAgICB2YWx1ZXNfdG8gPSAiQWJ1bmRhbmNlIgogICAgICApICU+JQogICAgICBtdXRhdGUoU2FtcGxlID0gZ3N1Yigiel8iLCAiIiwgU2FtcGxlKSkgICMgUmVtb3ZlICd6XycgcHJlZml4IGZvciBjbGVhbiBzYW1wbGUgbmFtZXMKICB9CgogICMgQ3JlYXRlIHRoZSBoZWF0bWFwCiAgaGVhdG1hcF9wbG90IDwtIGdncGxvdChkYXRhX2xvbmcsIGFlcyh4ID0gU2FtcGxlLCB5ID0gU3ltYm9sLCBmaWxsID0gQWJ1bmRhbmNlKSkgKwogICAgZ2VvbV90aWxlKGNvbG9yID0gIndoaXRlIikgKwogICAgc2NhbGVfZmlsbF9ncmFkaWVudG4oCiAgICAgIGNvbG9ycyA9IGNvbG9ycywKICAgICAgdmFsdWVzID0gc2NhbGVzOjpyZXNjYWxlKHNjYWxlX3ZhbHVlcyksCiAgICAgIG5hLnZhbHVlID0gbmFfY29sb3IsCiAgICAgIGd1aWRlID0gZ3VpZGVfY29sb3JiYXIoCiAgICAgICAgYmFyd2lkdGggPSAxLAogICAgICAgIGJhcmhlaWdodCA9IDEwLAogICAgICAgIHRpdGxlLnBvc2l0aW9uID0gInRvcCIsCiAgICAgICAgdGl0bGUuaGp1c3QgPSAwLjUKICAgICAgKQogICAgKSArCiAgICB0aGVtZV9taW5pbWFsKCkgKwogICAgdGhlbWUoCiAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSksCiAgICAgIGFzcGVjdC5yYXRpbyA9IDEgLyB0aWxlX3dpZHRoICMgQWRqdXN0IGFzcGVjdCByYXRpbwogICAgKSArCiAgICBsYWJzKHRpdGxlID0gIlByb3RlaW4gQWJ1bmRhbmNlIEhlYXRtYXAgKFotU2NvcmUpIiwgeCA9ICJTYW1wbGVzIiwgeSA9ICJQcm90ZWlucyIpCiAgCiAgcmV0dXJuKGhlYXRtYXBfcGxvdCkKfQoKIyBFeGFtcGxlIHVzYWdlCmhlYXRtYXBfcGxvdCA8LSBwbG90X3Byb3RlaW5faGVhdG1hcF96c2NvcmUoCiAgZGF0YSA9IGRmLAogIHByb3RlaW5zID0gdG9wX2dlbmVzLCAjIEV4YW1wbGUgcHJvdGVpbiBuYW1lcwogIHNhbXBsZV9wYXR0ZXJucyA9IGMoIkNvbnRyb2wiLCAiUElOSzEuS08iKSwKICBjb2xvcnMgPSBjKCJzbm93IiwgImxpZ2h0Z29sZGVucm9kMSIsICJnb2xkMSIsICJkYXJrb3JhbmdlMSIsICJyZWQyIiwgImZpcmVicmljazQiKSwKICBzY2FsZV92YWx1ZXMgPSBjKC0yLjUsIC0yLCAtMSwgMCwgMSwgMiwgMi41KSwgIyBBZGp1c3QgYmFzZWQgb24geW91ciBkYXRhIHJhbmdlCiAgZ3JvdXBfbWVhbnMgPSBUUlVFLCAjIFNldCB0byBGQUxTRSBpZiB5b3Ugd2FudCBpbmRpdmlkdWFsIHNhbXBsZXMKICB0aWxlX3dpZHRoID0gMC4yNSAjIEFkanVzdCB0aGUgd2lkdGggb2YgdGhlIHRpbGVzIChkZWZhdWx0IGlzIDAuOSkKKQoKIyBQcmludCB0aGUgcGxvdApwcmludChoZWF0bWFwX3Bsb3QpCgoKYGBgCgpGdW5jdGlvbiB0byBzZWUgdGhlIGdlbmUgZXhwcmVzc2lvbgpgYGB7cn0KCiMgRnVuY3Rpb24gdG8gcGxvdCBoZWF0bWFwIG9mIHJlbGF0aXZlIGFidW5kYW5jZSB3aXRoIFotc2NvcmVzCnByb3RlaW5fenNjb3JlIDwtIGZ1bmN0aW9uKGRhdGEsIHByb3RlaW5zLCBzYW1wbGVfcGF0dGVybnMsIGdyb3VwX21lYW5zID0gRkFMU0UpIHsKICAjIEZpbHRlciB0aGUgZGF0YSBmb3Igc2VsZWN0ZWQgcHJvdGVpbnMKICBkYXRhX2ZpbHRlcmVkIDwtIGRhdGEgJT4lCiAgICBmaWx0ZXIoU3ltYm9sICVpbiUgcHJvdGVpbnMpCiAgCiAgIyBTZXQgdGhlIG9yZGVyIG9mIHRoZSBTeW1ib2wgZmFjdG9yIGJhc2VkIG9uIHRoZSBpbnB1dCB2ZWN0b3IgJ3Byb3RlaW5zJwogIGRhdGFfZmlsdGVyZWQkU3ltYm9sIDwtIGZhY3RvcihkYXRhX2ZpbHRlcmVkJFN5bWJvbCwgbGV2ZWxzID0gcHJvdGVpbnMpCgogICMgSWRlbnRpZnkgc2FtcGxlIGNvbHVtbnMgbWF0Y2hpbmcgcGF0dGVybnMKICBzYW1wbGVfY29sdW1ucyA8LSBjb2xuYW1lcyhkYXRhX2ZpbHRlcmVkKVtzYXBwbHkoY29sbmFtZXMoZGF0YV9maWx0ZXJlZCksIGZ1bmN0aW9uKGNvbF9uYW1lKSB7CiAgICBhbnkoc2FwcGx5KHNhbXBsZV9wYXR0ZXJucywgZnVuY3Rpb24ocCkgZ3JlcGwocCwgY29sX25hbWUpKSkKICB9KV0KCiAgIyBEZWJ1ZzogQ2hlY2sgY29udGVudHMgb2Ygc2FtcGxlX2NvbHVtbnMKICBwcmludChwYXN0ZSgiU2FtcGxlIGNvbHVtbnMgc2VsZWN0ZWQ6IiwgcGFzdGUoc2FtcGxlX2NvbHVtbnMsIGNvbGxhcHNlID0gIiwgIikpKQoKICAjIENoZWNrIGlmIHNhbXBsZV9jb2x1bW5zIGhhcyB2YWxpZCBlbnRyaWVzCiAgaWYgKGxlbmd0aChzYW1wbGVfY29sdW1ucykgPT0gMCkgewogICAgc3RvcCgiTm8gc2FtcGxlIGNvbHVtbnMgbWF0Y2hlZCB0aGUgcGF0dGVybnMgcHJvdmlkZWQuIikKICB9CgogICMgU2VsZWN0IG9ubHkgY29sdW1ucyBtYXRjaGluZyBzYW1wbGUgcGF0dGVybnMgYW5kIHRoZSBTeW1ib2wgY29sdW1uCiAgZGF0YV9maWx0ZXJlZCA8LSBkYXRhX2ZpbHRlcmVkICU+JQogICAgZHBseXI6OnNlbGVjdChTeW1ib2wsIGFsbF9vZihzYW1wbGVfY29sdW1ucykpCgogICMgUmVtb3ZlIHJvd3Mgd2hlcmUgYWxsIHZhbHVlcyBhcmUgTkEgKGV4Y2x1ZGluZyB0aGUgU3ltYm9sIGNvbHVtbikKICBkYXRhX2ZpbHRlcmVkIDwtIGRhdGFfZmlsdGVyZWQgJT4lCiAgICBmaWx0ZXIocm93U3Vtcyhpcy5uYShkcGx5cjo6c2VsZWN0KC4sIC1TeW1ib2wpKSkgPCBsZW5ndGgoc2FtcGxlX2NvbHVtbnMpKQoKICBpZiAoZ3JvdXBfbWVhbnMpIHsKICAgICMgR3JvdXAgc2FtcGxlcyBieSB0aGUgYmFzZSBuYW1lIGFuZCBjYWxjdWxhdGUgbWVhbgogICAgc2FtcGxlX2Jhc2UgPC0gZ3N1YigiXFwuXFxkKyQiLCAiIiwgY29sbmFtZXMoZGF0YV9maWx0ZXJlZClbLTFdKQogICAgZGF0YV9ncm91cGVkIDwtIGRhdGFfZmlsdGVyZWQgJT4lCiAgICAgIHBpdm90X2xvbmdlcihjb2xzID0gLVN5bWJvbCwgbmFtZXNfdG8gPSAiU2FtcGxlIiwgdmFsdWVzX3RvID0gIkFidW5kYW5jZSIpICU+JQogICAgICBtdXRhdGUoU2FtcGxlQmFzZSA9IGdzdWIoIlxcLlxcZCskIiwgIiIsIFNhbXBsZSkpICU+JQogICAgICBncm91cF9ieShTeW1ib2wsIFNhbXBsZUJhc2UpICU+JQogICAgICBzdW1tYXJpemUoQWJ1bmRhbmNlID0gbWVhbihBYnVuZGFuY2UsIG5hLnJtID0gVFJVRSksIC5ncm91cHMgPSAnZHJvcCcpICU+JQogICAgICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gU2FtcGxlQmFzZSwgdmFsdWVzX2Zyb20gPSBBYnVuZGFuY2UpCgogICAgIyBDYWxjdWxhdGUgWi1zY29yZXMKICAgIGRhdGFfenNjb3JlIDwtIGRhdGFfZ3JvdXBlZCAlPiUKICAgICAgbXV0YXRlKGFjcm9zcygtU3ltYm9sLCB+IHNjYWxlKC4pWywgMV0sIC5uYW1lcyA9ICJ6X3tjb2x9IikpCgogICAgIyBSZXNoYXBlIGRhdGEgZm9yIGdncGxvdAogICAgZGF0YV9sb25nIDwtIGRhdGFfenNjb3JlICU+JQogICAgICBwaXZvdF9sb25nZXIoCiAgICAgICAgY29scyA9IHN0YXJ0c193aXRoKCJ6XyIpLCAKICAgICAgICBuYW1lc190byA9ICJTYW1wbGUiLCAKICAgICAgICB2YWx1ZXNfdG8gPSAiQWJ1bmRhbmNlIgogICAgICApICU+JQogICAgICBtdXRhdGUoU2FtcGxlID0gZ3N1Yigiel8iLCAiIiwgU2FtcGxlKSkgICMgUmVtb3ZlICd6XycgcHJlZml4IGZvciBjbGVhbiBzYW1wbGUgbmFtZXMKICB9IGVsc2UgewogICAgIyBDYWxjdWxhdGUgWi1zY29yZXMgZm9yIGVhY2ggcHJvdGVpbiBhY3Jvc3MgdGhlIHNlbGVjdGVkIHNhbXBsZXMKICAgIGRhdGFfenNjb3JlIDwtIGRhdGFfZmlsdGVyZWQgJT4lCiAgICAgIG11dGF0ZShhY3Jvc3MoYWxsX29mKHNhbXBsZV9jb2x1bW5zKSwgfiBzY2FsZSguKVssIDFdLCAubmFtZXMgPSAiel97Y29sfSIpKQoKICAgICMgUmVzaGFwZSBkYXRhIGZvciBnZ3Bsb3QKICAgIGRhdGFfbG9uZyA8LSBkYXRhX3pzY29yZSAlPiUKICAgICAgcGl2b3RfbG9uZ2VyKAogICAgICAgIGNvbHMgPSBzdGFydHNfd2l0aCgiel8iKSwgCiAgICAgICAgbmFtZXNfdG8gPSAiU2FtcGxlIiwgCiAgICAgICAgdmFsdWVzX3RvID0gIkFidW5kYW5jZSIKICAgICAgKSAlPiUKICAgICAgbXV0YXRlKFNhbXBsZSA9IGdzdWIoInpfIiwgIiIsIFNhbXBsZSkpICAjIFJlbW92ZSAnel8nIHByZWZpeCBmb3IgY2xlYW4gc2FtcGxlIG5hbWVzCiAgfQogIAogIHJldHVybihkYXRhX2xvbmcpCn0KCmRmLmxvbmcgPC0gcHJvdGVpbl96c2NvcmUoZGF0YSA9IGRmLAogIHByb3RlaW5zID0gdG9wX2dlbmVzLCAjIEV4YW1wbGUgcHJvdGVpbiBuYW1lcwogIHNhbXBsZV9wYXR0ZXJucyA9IGMoIkNvbnRyb2wiLCAiUElOSzEuS08iKSwgZ3JvdXBfbWVhbnMgPSBUUlVFKSAKICAKbWF4KGRmLmxvbmckQWJ1bmRhbmNlKQptaW4oZGYubG9uZyRBYnVuZGFuY2UpCiAgCmBgYAoKCgoKCkNoZWNrIGVhY2ggY29udHJhc3QKCmBgYHtyfQoKdG9wX2dlbmVzIDwtIHNlbGVjdF90b3BfZ2VuZXMoZmlsdGVyZWRfREVQJGBQSU5LMS1LT2AsIG4gPSAxMCkKCnBsb3RfcHJvdGVpbl9oZWF0bWFwX3pzY29yZSgKICBkYXRhID0gZGYsCiAgcHJvdGVpbnMgPSB0b3BfZ2VuZXMsICMgRXhhbXBsZSBwcm90ZWluIG5hbWVzCiAgc2FtcGxlX3BhdHRlcm5zID0gYygiQ29udHJvbCIsICJQSU5LMS5LTyIpLAogIGNvbG9ycyA9IGMoInNub3ciLCAibGlnaHRnb2xkZW5yb2QxIiwgImdvbGQxIiwgImRhcmtvcmFuZ2UxIiwgInJlZDIiLCAiZmlyZWJyaWNrNCIpLAogIHNjYWxlX3ZhbHVlcyA9IGMoLTAuNSwgLTAuMjUsIDAsIDEsIDIsIDQpLCAjIEFkanVzdCBiYXNlZCBvbiB5b3VyIGRhdGEgcmFuZ2UKICBncm91cF9tZWFucyA9IFRSVUUsICMgU2V0IHRvIEZBTFNFIGlmIHlvdSB3YW50IGluZGl2aWR1YWwgc2FtcGxlcwogICB0aWxlX3dpZHRoID0gMC4yNQopCgpwbG90X3Byb3RlaW5faGVhdG1hcF96c2NvcmUoCiAgZGF0YSA9IGRmLAogIHByb3RlaW5zID0gdG9wX2dlbmVzLCAjIEV4YW1wbGUgcHJvdGVpbiBuYW1lcwogIHNhbXBsZV9wYXR0ZXJucyA9IGMoIkNvbnRyb2wiLCAiUElOSzEuS08iKSwKICBjb2xvcnMgPSBjKCJzbm93IiwgImxpZ2h0Z29sZGVucm9kMSIsICJnb2xkMSIsICJkYXJrb3JhbmdlMSIsICJyZWQyIiwgImZpcmVicmljazQiKSwKICBzY2FsZV92YWx1ZXMgPSBjKC0wLjUsIC0wLjI1LCAwLCAxLCAyLCA0KSwgIyBBZGp1c3QgYmFzZWQgb24geW91ciBkYXRhIHJhbmdlCiAgZ3JvdXBfbWVhbnMgPSBGQUxTRSwjIFNldCB0byBGQUxTRSBpZiB5b3Ugd2FudCBpbmRpdmlkdWFsIHNhbXBsZXMKICAgdGlsZV93aWR0aCA9IDAuMjUKKQoKCgpgYGAKCmBgYHtyfQoKIyBQSU5LMSBERVAKdG9wX2dlbmVzIDwtIGMoIkxNTkEiLCJEQ04iLCJIREdGIiwiQ0EyIiwiTkVGTCIsIk5FRk0iLCJTWVQyIiwiU1RYMUEiKQpkZi5sb25nIDwtIHByb3RlaW5fenNjb3JlKGRhdGEgPSBkZiwKICBwcm90ZWlucyA9IHRvcF9nZW5lcywgIyBFeGFtcGxlIHByb3RlaW4gbmFtZXMKICBzYW1wbGVfcGF0dGVybnMgPSBjKCJDb250cm9sIiwgIlBJTksxLktPIiksIGdyb3VwX21lYW5zID0gVFJVRSkgCiAgCm1heChkZi5sb25nJEFidW5kYW5jZSkKbWluKGRmLmxvbmckQWJ1bmRhbmNlKQoKCnBsb3RfcHJvdGVpbl9oZWF0bWFwX3pzY29yZSgKICBkYXRhID0gZGYsCiAgcHJvdGVpbnMgPSB0b3BfZ2VuZXMsICMgRXhhbXBsZSBwcm90ZWluIG5hbWVzCiAgc2FtcGxlX3BhdHRlcm5zID0gYygiQ29udHJvbCIsICJQSU5LMS5LTyIpLAogIGNvbG9ycyA9IGMoInNub3ciLCAibGlnaHRnb2xkZW5yb2QxIiwgImdvbGQxIiwgImRhcmtvcmFuZ2UxIiwgInJlZDIiLCAiZmlyZWJyaWNrNCIpLAogIHNjYWxlX3ZhbHVlcyA9IGMoLTAuOSwtMC42LC0wLjIsIDAsIDIsIDIuNSksICMgQWRqdXN0IGJhc2VkIG9uIHlvdXIgZGF0YSByYW5nZQogIGdyb3VwX21lYW5zID0gVFJVRSwgIyBTZXQgdG8gRkFMU0UgaWYgeW91IHdhbnQgaW5kaXZpZHVhbCBzYW1wbGVzCiAgIHRpbGVfd2lkdGggPSAwLjI1CikKCnBsb3RfcHJvdGVpbl9oZWF0bWFwX3pzY29yZSgKICBkYXRhID0gZGYsCiAgcHJvdGVpbnMgPSB0b3BfZ2VuZXMsICMgRXhhbXBsZSBwcm90ZWluIG5hbWVzCiAgc2FtcGxlX3BhdHRlcm5zID0gYygiQ29udHJvbCIsICJQSU5LMS5LTyIpLAogIGNvbG9ycyA9IGMoInNub3ciLCAibGlnaHRnb2xkZW5yb2QxIiwgImdvbGQxIiwgImRhcmtvcmFuZ2UxIiwgInJlZDIiLCAiZmlyZWJyaWNrNCIpLAogIHNjYWxlX3ZhbHVlcyA9IGMoLTAuOSwtMC42LC0wLjIsIDAsIDIsIDIuNSksICMgQWRqdXN0IGJhc2VkIG9uIHlvdXIgZGF0YSByYW5nZQogIGdyb3VwX21lYW5zID0gRkFMU0UsIyBTZXQgdG8gRkFMU0UgaWYgeW91IHdhbnQgaW5kaXZpZHVhbCBzYW1wbGVzCiAgIHRpbGVfd2lkdGggPSAwLjI1CikKCmBgYAoKYGBge3J9CmNvbG5hbWVzKGRmKQpgYGAKCgoKU05DQS1BNTNUCgpgYGB7cn0KdG9wX2dlbmVzIDwtIHNlbGVjdF90b3BfZ2VuZXMoZmlsdGVyZWRfREVQJGBTTkNBLUE1M1RgLCBuID0gMTApCgpkZi5sb25nIDwtIHByb3RlaW5fenNjb3JlKGRhdGEgPSBkZiwKICBwcm90ZWlucyA9IHRvcF9nZW5lcywgIyBFeGFtcGxlIHByb3RlaW4gbmFtZXMKICBzYW1wbGVfcGF0dGVybnMgPSBjKCJDb250cm9sIiwgIkE1M1QiKSwgZ3JvdXBfbWVhbnMgPSBUUlVFKSAKICAKbWF4KGRmLmxvbmckQWJ1bmRhbmNlKQptaW4oZGYubG9uZyRBYnVuZGFuY2UpCgpwbG90X3Byb3RlaW5faGVhdG1hcF96c2NvcmUoCiAgZGF0YSA9IGRmLAogIHByb3RlaW5zID0gdG9wX2dlbmVzLCAjIEV4YW1wbGUgcHJvdGVpbiBuYW1lcwogIHNhbXBsZV9wYXR0ZXJucyA9IGMoIkNvbnRyb2wiLCAiQTUzVCIpLAogIGNvbG9ycyA9IGMoInNub3ciLCAibGlnaHRnb2xkZW5yb2QxIiwgImdvbGQxIiwgImRhcmtvcmFuZ2UxIiwgInJlZDIiLCAiZmlyZWJyaWNrNCIpLAogIHNjYWxlX3ZhbHVlcyA9IGMoLTEsIC0wLjUsLTAuMjUsIDAsIDEsIDIsIDQpLCAjIEFkanVzdCBiYXNlZCBvbiB5b3VyIGRhdGEgcmFuZ2UKICBncm91cF9tZWFucyA9IFRSVUUsICMgU2V0IHRvIEZBTFNFIGlmIHlvdSB3YW50IGluZGl2aWR1YWwgc2FtcGxlcwogICB0aWxlX3dpZHRoID0gMC4yNQopCgpwbG90X3Byb3RlaW5faGVhdG1hcF96c2NvcmUoCiAgZGF0YSA9IGRmLAogIHByb3RlaW5zID0gdG9wX2dlbmVzLCAjIEV4YW1wbGUgcHJvdGVpbiBuYW1lcwogIHNhbXBsZV9wYXR0ZXJucyA9IGMoIkNvbnRyb2wiLCAiQTUzVCIpLAogIGNvbG9ycyA9IGMoInNub3ciLCAibGlnaHRnb2xkZW5yb2QxIiwgImdvbGQxIiwgImRhcmtvcmFuZ2UxIiwgInJlZDIiLCAiZmlyZWJyaWNrNCIpLAogIHNjYWxlX3ZhbHVlcyA9IGMoLTEsIC0wLjUsIC0wLjI1LDAsIDEsIDIsIDQpLCAjIEFkanVzdCBiYXNlZCBvbiB5b3VyIGRhdGEgcmFuZ2UKICBncm91cF9tZWFucyA9IEZBTFNFLCMgU2V0IHRvIEZBTFNFIGlmIHlvdSB3YW50IGluZGl2aWR1YWwgc2FtcGxlcwogICB0aWxlX3dpZHRoID0gMC4yNQopCgpgYGAKR0JBCmBgYHtyfQp0b3BfZ2VuZXMgPC0gc2VsZWN0X3RvcF9nZW5lcyhmaWx0ZXJlZF9ERVAkYEdCQS1LT2AsIG4gPSAxMCkKCmRmLmxvbmcgPC0gcHJvdGVpbl96c2NvcmUoZGF0YSA9IGRmLAogIHByb3RlaW5zID0gdG9wX2dlbmVzLCAjIEV4YW1wbGUgcHJvdGVpbiBuYW1lcwogIHNhbXBsZV9wYXR0ZXJucyA9IGMoIkNvbnRyb2wiLCAiR0JBLktPIiksIGdyb3VwX21lYW5zID0gVFJVRSkgCiAgCm1heChkZi5sb25nJEFidW5kYW5jZSkKbWluKGRmLmxvbmckQWJ1bmRhbmNlKQoKcGxvdF9wcm90ZWluX2hlYXRtYXBfenNjb3JlKAogIGRhdGEgPSBkZiwKICBwcm90ZWlucyA9IHRvcF9nZW5lcywgIyBFeGFtcGxlIHByb3RlaW4gbmFtZXMKICBzYW1wbGVfcGF0dGVybnMgPSBjKCJDb250cm9sIiwgIkdCQS5LTyIpLAogIGNvbG9ycyA9IGMoInNub3ciLCAibGlnaHRnb2xkZW5yb2QxIiwgImdvbGQxIiwgImRhcmtvcmFuZ2UxIiwgInJlZDIiLCAiZmlyZWJyaWNrNCIpLAogIHNjYWxlX3ZhbHVlcyA9IGMoLTEsIC0wLjUsIC0wLjI1LDAsIDEsIDIsIDMuNSksICMgQWRqdXN0IGJhc2VkIG9uIHlvdXIgZGF0YSByYW5nZQogIGdyb3VwX21lYW5zID0gVFJVRSwgIyBTZXQgdG8gRkFMU0UgaWYgeW91IHdhbnQgaW5kaXZpZHVhbCBzYW1wbGVzCiAgIHRpbGVfd2lkdGggPSAwLjI1CikKCnBsb3RfcHJvdGVpbl9oZWF0bWFwX3pzY29yZSgKICBkYXRhID0gZGYsCiAgcHJvdGVpbnMgPSB0b3BfZ2VuZXMsICMgRXhhbXBsZSBwcm90ZWluIG5hbWVzCiAgc2FtcGxlX3BhdHRlcm5zID0gYygiQ29udHJvbCIsICJHQkEuS08iKSwKICBjb2xvcnMgPSBjKCJzbm93IiwgImxpZ2h0Z29sZGVucm9kMSIsICJnb2xkMSIsICJkYXJrb3JhbmdlMSIsICJyZWQyIiwgImZpcmVicmljazQiKSwKICBzY2FsZV92YWx1ZXMgPSBjKC0xLCAtMC41LCAtMC4yNSwwLCAxLCAyLCAzLjUpLCAjIEFkanVzdCBiYXNlZCBvbiB5b3VyIGRhdGEgcmFuZ2UKICBncm91cF9tZWFucyA9IEZBTFNFLCMgU2V0IHRvIEZBTFNFIGlmIHlvdSB3YW50IGluZGl2aWR1YWwgc2FtcGxlcwogICB0aWxlX3dpZHRoID0gMC4yNQopCmBgYApQYXJraW4gIEtPCgpgYGB7cn0KdG9wX2dlbmVzIDwtIHNlbGVjdF90b3BfZ2VuZXMoZmlsdGVyZWRfREVQJGBQUktOLUtPYCwgbiA9IDEwKQoKZGYubG9uZyA8LSBwcm90ZWluX3pzY29yZShkYXRhID0gZGYsCiAgcHJvdGVpbnMgPSB0b3BfZ2VuZXMsICMgRXhhbXBsZSBwcm90ZWluIG5hbWVzCiAgc2FtcGxlX3BhdHRlcm5zID0gYygiQ29udHJvbCIsICJQUktOLktPIiksIGdyb3VwX21lYW5zID0gVFJVRSkgCiAgCm1heChkZi5sb25nJEFidW5kYW5jZSkKbWluKGRmLmxvbmckQWJ1bmRhbmNlKQoKcGxvdF9wcm90ZWluX2hlYXRtYXBfenNjb3JlKAogIGRhdGEgPSBkZiwKICBwcm90ZWlucyA9IHRvcF9nZW5lcywgIyBFeGFtcGxlIHByb3RlaW4gbmFtZXMKICBzYW1wbGVfcGF0dGVybnMgPSBjKCJDb250cm9sIiwgIlBSS04uS08iKSwKICBjb2xvcnMgPSBjKCJzbm93IiwgImxpZ2h0Z29sZGVucm9kMSIsICJnb2xkMSIsICJkYXJrb3JhbmdlMSIsICJyZWQyIiwgImZpcmVicmljazQiKSwKICBzY2FsZV92YWx1ZXMgPSBjKC0xLCAtMC41LCAtMC4yNSwwLCAxLCAyLCAzLjUpLCAjIEFkanVzdCBiYXNlZCBvbiB5b3VyIGRhdGEgcmFuZ2UKICBncm91cF9tZWFucyA9IFRSVUUsICMgU2V0IHRvIEZBTFNFIGlmIHlvdSB3YW50IGluZGl2aWR1YWwgc2FtcGxlcwogICB0aWxlX3dpZHRoID0gMC4yNQopCgpwbG90X3Byb3RlaW5faGVhdG1hcF96c2NvcmUoCiAgZGF0YSA9IGRmLAogIHByb3RlaW5zID0gdG9wX2dlbmVzLCAjIEV4YW1wbGUgcHJvdGVpbiBuYW1lcwogIHNhbXBsZV9wYXR0ZXJucyA9IGMoIkNvbnRyb2wiLCAiUFJLTi5LTyIpLAogIGNvbG9ycyA9IGMoInNub3ciLCAibGlnaHRnb2xkZW5yb2QxIiwgImdvbGQxIiwgImRhcmtvcmFuZ2UxIiwgInJlZDIiLCAiZmlyZWJyaWNrNCIpLAogIHNjYWxlX3ZhbHVlcyA9IGMoLTEsIC0wLjUsIC0wLjI1LDAsIDEsIDIsIDMuNSksICMgQWRqdXN0IGJhc2VkIG9uIHlvdXIgZGF0YSByYW5nZQogIGdyb3VwX21lYW5zID0gRkFMU0UsIyBTZXQgdG8gRkFMU0UgaWYgeW91IHdhbnQgaW5kaXZpZHVhbCBzYW1wbGVzCiAgIHRpbGVfd2lkdGggPSAwLjI1CikKCmBgYAoKRm9yIHRoZSBkYXJrIGdlbm9tZSBnZW5lIGV4cHJlc3Npb24gbGV2ZWxzIEknbGwgbmVlZCB0aGUgb3RoZXIgZGF0YWZyYW1lCgpgYGB7cn0KCmFidW5kYW5jZS5kYXJrIDwtIHJlYWQuY3N2KCIvVXNlcnMvcmhhbGVuYXRob21hcy9Eb3dubG9hZHMvTW92ZV9EYXRhL0RhcmtHZW5vbWVSZXN1bHQvUHJvdG9taWNzTm9ybUdlbmVBYnVuZGFuY2VfZGFyay5jc3YiKQoKY29sbmFtZXMoYWJ1bmRhbmNlLmRhcmspCgpkZiA8LSBhYnVuZGFuY2UuZGFya1ssIGMoMyw1OjE2LDE4OjIwKV0KZGYuZGFyayA8LSBhYnVuZGFuY2UuZGFya1ssIGMoMyw1OjE2LDE4OjIwKV0KY29sbmFtZXMoZGYpCgoKCgpgYGAKCgpgYGB7cn0KdG9wX2dlbmVzIDwtIHNlbGVjdF90b3BfZ2VuZXMoZmlsdGVyZWRfREVQJGBJR1NGOUItS09gLCBuID0gMTApCgpkZi5sb25nIDwtIHByb3RlaW5fenNjb3JlKGRhdGEgPSBkZiwKICBwcm90ZWlucyA9IHRvcF9nZW5lcywgIyBFeGFtcGxlIHByb3RlaW4gbmFtZXMKICBzYW1wbGVfcGF0dGVybnMgPSBjKCJDb250cm9sIiwgIklHU0Y5Qi5LTyIpLCBncm91cF9tZWFucyA9IFRSVUUpIAogIAptYXgoZGYubG9uZyRBYnVuZGFuY2UpCm1pbihkZi5sb25nJEFidW5kYW5jZSkKCnBsb3RfcHJvdGVpbl9oZWF0bWFwX3pzY29yZSgKICBkYXRhID0gZGYsCiAgcHJvdGVpbnMgPSB0b3BfZ2VuZXMsICMgRXhhbXBsZSBwcm90ZWluIG5hbWVzCiAgc2FtcGxlX3BhdHRlcm5zID0gYygiQ29udHJvbCIsICJJR1NGOUIuS08iKSwKICBjb2xvcnMgPSBjKCJzbm93IiwgImxpZ2h0Z29sZGVucm9kMSIsICJnb2xkMSIsICJkYXJrb3JhbmdlMSIsICJyZWQyIiwgImZpcmVicmljazQiKSwKICBzY2FsZV92YWx1ZXMgPSBjKC0xLCAtMC41LCAtMC4yNSwwLCAxLCAyLCAzLjUpLCAjIEFkanVzdCBiYXNlZCBvbiB5b3VyIGRhdGEgcmFuZ2UKICBncm91cF9tZWFucyA9IFRSVUUsICMgU2V0IHRvIEZBTFNFIGlmIHlvdSB3YW50IGluZGl2aWR1YWwgc2FtcGxlcwogICB0aWxlX3dpZHRoID0gMC4yNQopCgpwbG90X3Byb3RlaW5faGVhdG1hcF96c2NvcmUoCiAgZGF0YSA9IGRmLAogIHByb3RlaW5zID0gdG9wX2dlbmVzLCAjIEV4YW1wbGUgcHJvdGVpbiBuYW1lcwogIHNhbXBsZV9wYXR0ZXJucyA9IGMoIkNvbnRyb2wiLCAiSUdTRjlCLktPIiksCiAgY29sb3JzID0gYygic25vdyIsICJsaWdodGdvbGRlbnJvZDEiLCAiZ29sZDEiLCAiZGFya29yYW5nZTEiLCAicmVkMiIsICJmaXJlYnJpY2s0IiksCiAgc2NhbGVfdmFsdWVzID0gYygtMSwgLTAuNSwgLTAuMjUsMCwgMSwgMiwgMy41KSwgIyBBZGp1c3QgYmFzZWQgb24geW91ciBkYXRhIHJhbmdlCiAgZ3JvdXBfbWVhbnMgPSBGQUxTRSwjIFNldCB0byBGQUxTRSBpZiB5b3Ugd2FudCBpbmRpdmlkdWFsIHNhbXBsZXMKICAgdGlsZV93aWR0aCA9IDAuMjUKKQoKYGBgCgpgYGB7cn0KdG9wX2dlbmVzIDwtIHNlbGVjdF90b3BfZ2VuZXMoZmlsdGVyZWRfREVQJGBJTlBQNUYtS09gLCBuID0gMTApCgpkZi5sb25nIDwtIHByb3RlaW5fenNjb3JlKGRhdGEgPSBkZiwKICBwcm90ZWlucyA9IHRvcF9nZW5lcywgIyBFeGFtcGxlIHByb3RlaW4gbmFtZXMKICBzYW1wbGVfcGF0dGVybnMgPSBjKCJDb250cm9sIiwgIklOUFA1Ri5LTyIpLCBncm91cF9tZWFucyA9IFRSVUUpIAogIAptYXgoZGYubG9uZyRBYnVuZGFuY2UpCm1pbihkZi5sb25nJEFidW5kYW5jZSkKCnBsb3RfcHJvdGVpbl9oZWF0bWFwX3pzY29yZSgKICBkYXRhID0gZGYsCiAgcHJvdGVpbnMgPSB0b3BfZ2VuZXMsICMgRXhhbXBsZSBwcm90ZWluIG5hbWVzCiAgc2FtcGxlX3BhdHRlcm5zID0gYygiQ29udHJvbCIsICJJTlBQNUYuS08iKSwKICBjb2xvcnMgPSBjKCJzbm93IiwgImxpZ2h0Z29sZGVucm9kMSIsICJnb2xkMSIsICJkYXJrb3JhbmdlMSIsInJlZCIsICJyZWQyIiwgImZpcmVicmljazQiKSwKICBzY2FsZV92YWx1ZXMgPSBjKC0wLjc1LCAtMC41LCAtMC4yNSwwLCAxLCAyLCA0KSwgIyBBZGp1c3QgYmFzZWQgb24geW91ciBkYXRhIHJhbmdlCiAgZ3JvdXBfbWVhbnMgPSBUUlVFLCAjIFNldCB0byBGQUxTRSBpZiB5b3Ugd2FudCBpbmRpdmlkdWFsIHNhbXBsZXMKICAgdGlsZV93aWR0aCA9IDAuMjUKKQoKcGxvdF9wcm90ZWluX2hlYXRtYXBfenNjb3JlKAogIGRhdGEgPSBkZiwKICBwcm90ZWlucyA9IHRvcF9nZW5lcywgIyBFeGFtcGxlIHByb3RlaW4gbmFtZXMKICBzYW1wbGVfcGF0dGVybnMgPSBjKCJDb250cm9sIiwgIklOUFA1Ri5LTyIpLAogIGNvbG9ycyA9IGMoInNub3ciLCAibGlnaHRnb2xkZW5yb2QxIiwgImdvbGQxIiwgImRhcmtvcmFuZ2UxIiwicmVkIiwgInJlZDIiLCAiZmlyZWJyaWNrNCIpLAogIHNjYWxlX3ZhbHVlcyA9IGMoLTAuNzUsIC0wLjUsIC0wLjI1LDAsIDEsIDIsIDQpLCAjIEFkanVzdCBiYXNlZCBvbiB5b3VyIGRhdGEgcmFuZ2UKICBncm91cF9tZWFucyA9IEZBTFNFLCMgU2V0IHRvIEZBTFNFIGlmIHlvdSB3YW50IGluZGl2aWR1YWwgc2FtcGxlcwogICB0aWxlX3dpZHRoID0gMC4yNQopCgpgYGAKCgpgYGB7cn0KCnRvcF9nZW5lcyA8LSBzZWxlY3RfdG9wX2dlbmVzKGZpbHRlcmVkX0RFUCRgSVA2SzItS09gLCBuID0gMTApCgpkZi5sb25nIDwtIHByb3RlaW5fenNjb3JlKGRhdGEgPSBkZiwKICBwcm90ZWlucyA9IHRvcF9nZW5lcywgIyBFeGFtcGxlIHByb3RlaW4gbmFtZXMKICBzYW1wbGVfcGF0dGVybnMgPSBjKCJDb250cm9sIiwgIklQNksyLktPIiksIGdyb3VwX21lYW5zID0gVFJVRSkgCiAgCm1heChkZi5sb25nJEFidW5kYW5jZSkKbWluKGRmLmxvbmckQWJ1bmRhbmNlKQoKcGxvdF9wcm90ZWluX2hlYXRtYXBfenNjb3JlKAogIGRhdGEgPSBkZiwKICBwcm90ZWlucyA9IHRvcF9nZW5lcywgIyBFeGFtcGxlIHByb3RlaW4gbmFtZXMKICBzYW1wbGVfcGF0dGVybnMgPSBjKCJDb250cm9sIiwgIklQNksyLktPIiksCiAgY29sb3JzID0gYygic25vdyIsICJsaWdodGdvbGRlbnJvZDEiLCAiZ29sZDEiLCAiZGFya29yYW5nZTEiLCJyZWQiLCAicmVkMiIsICJmaXJlYnJpY2s0IiksCiAgc2NhbGVfdmFsdWVzID0gYygtMC43NSwgLTAuNSwgLTAuMjUsMCwgMSwgMiwgNCksICMgQWRqdXN0IGJhc2VkIG9uIHlvdXIgZGF0YSByYW5nZQogIGdyb3VwX21lYW5zID0gVFJVRSwgIyBTZXQgdG8gRkFMU0UgaWYgeW91IHdhbnQgaW5kaXZpZHVhbCBzYW1wbGVzCiAgIHRpbGVfd2lkdGggPSAwLjI1CikKCnBsb3RfcHJvdGVpbl9oZWF0bWFwX3pzY29yZSgKICBkYXRhID0gZGYsCiAgcHJvdGVpbnMgPSB0b3BfZ2VuZXMsICMgRXhhbXBsZSBwcm90ZWluIG5hbWVzCiAgc2FtcGxlX3BhdHRlcm5zID0gYygiQ29udHJvbCIsICJJUDZLMi5LTyIpLAogIGNvbG9ycyA9IGMoInNub3ciLCAibGlnaHRnb2xkZW5yb2QxIiwgImdvbGQxIiwgImRhcmtvcmFuZ2UxIiwicmVkIiwgInJlZDIiLCAiZmlyZWJyaWNrNCIpLAogIHNjYWxlX3ZhbHVlcyA9IGMoLTAuNzUsIC0wLjUsIC0wLjI1LDAsIDEsIDIsIDQpLCAjIEFkanVzdCBiYXNlZCBvbiB5b3VyIGRhdGEgcmFuZ2UKICBncm91cF9tZWFucyA9IEZBTFNFLCMgU2V0IHRvIEZBTFNFIGlmIHlvdSB3YW50IGluZGl2aWR1YWwgc2FtcGxlcwogICB0aWxlX3dpZHRoID0gMC4yNQopCgoKCmBgYAoKCmBgYHtyfQoKdG9wX2dlbmVzIDwtIHNlbGVjdF90b3BfZ2VuZXMoZmlsdGVyZWRfREVQJGBTSDNHTDItS09gLCBuID0gMTApCgpkZi5sb25nIDwtIHByb3RlaW5fenNjb3JlKGRhdGEgPSBkZiwKICBwcm90ZWlucyA9IHRvcF9nZW5lcywgIyBFeGFtcGxlIHByb3RlaW4gbmFtZXMKICBzYW1wbGVfcGF0dGVybnMgPSBjKCJDb250cm9sIiwgIlNIM0dMMi5LTyIpLCBncm91cF9tZWFucyA9IFRSVUUpIAogIAptYXgoZGYubG9uZyRBYnVuZGFuY2UpCm1pbihkZi5sb25nJEFidW5kYW5jZSkKCnBsb3RfcHJvdGVpbl9oZWF0bWFwX3pzY29yZSgKICBkYXRhID0gZGYsCiAgcHJvdGVpbnMgPSB0b3BfZ2VuZXMsICMgRXhhbXBsZSBwcm90ZWluIG5hbWVzCiAgc2FtcGxlX3BhdHRlcm5zID0gYygiQ29udHJvbCIsICJTSDNHTDIuS08iKSwKICBjb2xvcnMgPSBjKCJzbm93IiwgImxpZ2h0Z29sZGVucm9kMSIsICJnb2xkMSIsICJkYXJrb3JhbmdlMSIsInJlZCIsICJyZWQyIiwgImZpcmVicmljazQiKSwKICBzY2FsZV92YWx1ZXMgPSBjKC0wLjYsIC0wLjUsMC4yNSwgMCwgMSwgMy44LCA0LjEpLCAjIEFkanVzdCBiYXNlZCBvbiB5b3VyIGRhdGEgcmFuZ2UKICBncm91cF9tZWFucyA9IFRSVUUsICMgU2V0IHRvIEZBTFNFIGlmIHlvdSB3YW50IGluZGl2aWR1YWwgc2FtcGxlcwogICB0aWxlX3dpZHRoID0gMC4yNQopCgpwbG90X3Byb3RlaW5faGVhdG1hcF96c2NvcmUoCiAgZGF0YSA9IGRmLAogIHByb3RlaW5zID0gdG9wX2dlbmVzLCAjIEV4YW1wbGUgcHJvdGVpbiBuYW1lcwogIHNhbXBsZV9wYXR0ZXJucyA9IGMoIkNvbnRyb2wiLCAiU0gzR0wyLktPIiksCiAgY29sb3JzID0gYygic25vdyIsICJsaWdodGdvbGRlbnJvZDEiLCAiZ29sZDEiLCAiZGFya29yYW5nZTEiLCJyZWQiLCAicmVkMiIsICJmaXJlYnJpY2s0IiksCiAgc2NhbGVfdmFsdWVzID0gYygtMC42LCAtMC41LDAuMjUsIDAsIDEsIDMuOCwgNC4xKSwgIyBBZGp1c3QgYmFzZWQgb24geW91ciBkYXRhIHJhbmdlCiAgZ3JvdXBfbWVhbnMgPSBGQUxTRSwjIFNldCB0byBGQUxTRSBpZiB5b3Ugd2FudCBpbmRpdmlkdWFsIHNhbXBsZXMKICAgdGlsZV93aWR0aCA9IDAuMjUKKQoKCmBgYAoKYGBge3J9Cm5hbWVzKGZpbHRlcmVkX0RFUCkKCgpgYGAKCgojIGdlbmUgb3ZlcmxhcAoKYGBge3J9CgpsaWJyYXJ5KFVwU2V0UikKCgojIEV4dHJhY3QgZ2VuZSBsaXN0cyBmb3IgZWFjaCBjb21wYXJpc29uIGluIGZpbHRlcmVkX0RFUApnZW5lX2xpc3RzIDwtIGxhcHBseShmaWx0ZXJlZF9ERVAsIGZ1bmN0aW9uKGRmKSB1bmlxdWUoZGYkU3ltYm9sKSkKCiMgTmFtZSB0aGUgbGlzdHMgYWNjb3JkaW5nIHRvIHRoZSBjb250cmFzdCBuYW1lcwpuYW1lcyhnZW5lX2xpc3RzKSA8LSBuYW1lcyhmaWx0ZXJlZF9ERVApCgojIENyZWF0ZSBhIGNvbWJpbmVkIGxpc3Qgb2YgYWxsIHVuaXF1ZSBnZW5lcwphbGxfZ2VuZXMgPC0gdW5pcXVlKHVubGlzdChnZW5lX2xpc3RzKSkKCiMgSW5pdGlhbGl6ZSBhIGRhdGEgZnJhbWUgdG8gc3RvcmUgYmluYXJ5IHByZXNlbmNlL2Fic2VuY2UgZGF0YQpnZW5lX21hdHJpeCA8LSBkYXRhLmZyYW1lKFN5bWJvbCA9IGFsbF9nZW5lcykKCiMgTG9vcCB0aHJvdWdoIGVhY2ggY29tcGFyaXNvbiBhbmQgY3JlYXRlIGJpbmFyeSBjb2x1bW5zCmZvciAoY29udHJhc3QgaW4gbmFtZXMoZ2VuZV9saXN0cykpIHsKICBnZW5lX21hdHJpeFtbY29udHJhc3RdXSA8LSBhcy5udW1lcmljKGdlbmVfbWF0cml4JFN5bWJvbCAlaW4lIGdlbmVfbGlzdHNbW2NvbnRyYXN0XV0pCn0KCiMgRGVidWc6IENoZWNrIHRoZSBzdHJ1Y3R1cmUgb2YgdGhlIGdlbmVfbWF0cml4CnN0cihnZW5lX21hdHJpeCkKCgojIENyZWF0ZSB0aGUgVXBTZXQgcGxvdAp1cHNldCgKICBnZW5lX21hdHJpeCwKICBzZXRzID0gbmFtZXMoZ2VuZV9saXN0cyksCiAgc2V0cy5iYXIuY29sb3IgPSAiIzU2QjRFOSIsCiAgb3JkZXIuYnkgPSAiZnJlcSIsCiAgZW1wdHkuaW50ZXJzZWN0aW9ucyA9ICJvbiIsCiAga2VlcC5vcmRlciA9IFRSVUUKKQoKCgoKYGBgCgpDb250cm9sIHRoZSBvcmRlciAKYGBge3J9CiMgSW5zdGFsbCBVcFNldFIgcGFja2FnZSBpZiBub3QgYWxyZWFkeSBpbnN0YWxsZWQKaWYgKCFyZXF1aXJlTmFtZXNwYWNlKCJVcFNldFIiLCBxdWlldGx5ID0gVFJVRSkpIHsKICBpbnN0YWxsLnBhY2thZ2VzKCJVcFNldFIiKQp9CgojIExvYWQgdGhlIHJlcXVpcmVkIGxpYnJhcmllcwpsaWJyYXJ5KFVwU2V0UikKbGlicmFyeShkcGx5cikKCmNyZWF0ZV91cHNldF9wbG90IDwtIGZ1bmN0aW9uKGZpbHRlcmVkX0RFUCwgY29udHJhc3Rfb3JkZXIsIGNvbG9ycywgdGV4dF9zY2FsZSA9IDEuNSkgewogICMgRW5zdXJlIHRoZSBsZW5ndGggb2YgY29sb3JzIG1hdGNoZXMgdGhlIGxlbmd0aCBvZiBjb250cmFzdF9vcmRlcgogIGlmIChsZW5ndGgoY29sb3JzKSAhPSBsZW5ndGgoY29udHJhc3Rfb3JkZXIpKSB7CiAgICBzdG9wKCJUaGUgbGVuZ3RoIG9mIHRoZSAnY29sb3JzJyB2ZWN0b3IgbXVzdCBtYXRjaCB0aGUgbGVuZ3RoIG9mICdjb250cmFzdF9vcmRlcicuIikKICB9CiAgCiAgIyBFeHRyYWN0IGdlbmUgbGlzdHMgZm9yIGVhY2ggY29tcGFyaXNvbiBpbiBmaWx0ZXJlZF9ERVAKICBnZW5lX2xpc3RzIDwtIGxhcHBseShmaWx0ZXJlZF9ERVAsIGZ1bmN0aW9uKGRmKSB1bmlxdWUoZGYkU3ltYm9sKSkKICAKICAjIE5hbWUgdGhlIGxpc3RzIGFjY29yZGluZyB0byB0aGUgY29udHJhc3QgbmFtZXMKICBuYW1lcyhnZW5lX2xpc3RzKSA8LSBuYW1lcyhmaWx0ZXJlZF9ERVApCiAgCiAgIyBDcmVhdGUgYSBjb21iaW5lZCBsaXN0IG9mIGFsbCB1bmlxdWUgZ2VuZXMKICBhbGxfZ2VuZXMgPC0gdW5pcXVlKHVubGlzdChnZW5lX2xpc3RzKSkKICAKICAjIEluaXRpYWxpemUgYSBkYXRhIGZyYW1lIHRvIHN0b3JlIGJpbmFyeSBwcmVzZW5jZS9hYnNlbmNlIGRhdGEKICBnZW5lX21hdHJpeCA8LSBkYXRhLmZyYW1lKFN5bWJvbCA9IGFsbF9nZW5lcykKICAKICAjIExvb3AgdGhyb3VnaCBlYWNoIGNvbXBhcmlzb24gYW5kIGNyZWF0ZSBiaW5hcnkgY29sdW1ucwogIGZvciAoY29udHJhc3QgaW4gbmFtZXMoZ2VuZV9saXN0cykpIHsKICAgIGdlbmVfbWF0cml4W1tjb250cmFzdF1dIDwtIGFzLm51bWVyaWMoZ2VuZV9tYXRyaXgkU3ltYm9sICVpbiUgZ2VuZV9saXN0c1tbY29udHJhc3RdXSkKICB9CiAgCiAgIyBSZW9yZGVyIHRoZSBnZW5lX21hdHJpeCBjb2x1bW5zIHRvIG1hdGNoIHRoZSBkZXNpcmVkIGNvbnRyYXN0IG9yZGVyCiAgZ2VuZV9tYXRyaXggPC0gZ2VuZV9tYXRyaXggJT4lCiAgICBkcGx5cjo6c2VsZWN0KFN5bWJvbCwgYWxsX29mKGNvbnRyYXN0X29yZGVyKSkKCiAgIyBEZWJ1ZzogQ2hlY2sgdGhlIHN0cnVjdHVyZSBvZiB0aGUgZ2VuZV9tYXRyaXgKICBwcmludChzdHIoZ2VuZV9tYXRyaXgpKQogIAogICMgQ3JlYXRlIHRoZSBVcFNldCBwbG90IHdpdGggY3VzdG9tIGNvbG9ycwogIHVwc2V0KAogICAgZ2VuZV9tYXRyaXgsCiAgICBzZXRzID0gY29udHJhc3Rfb3JkZXIsICAjIFVzZSB0aGUgc3BlY2lmaWVkIG9yZGVyIGZvciBjb250cmFzdHMKICAgIHNldHMuYmFyLmNvbG9yID0gY29sb3JzLCAjIEFwcGx5IHRoZSBzcGVjaWZpZWQgY29sb3JzIGluIG9yZGVyCiAgICBvcmRlci5ieSA9ICJmcmVxIiwKICAgIGVtcHR5LmludGVyc2VjdGlvbnMgPSAib24iLAogICAga2VlcC5vcmRlciA9IFRSVUUsCiAgICB0ZXh0LnNjYWxlID0gdGV4dF9zY2FsZQogICkKfQoKCmNvbG9ycyA8LWMoIiNkMzRhOTgiLCIjNDM5NDcyIiwiIzVjMWM5NyIsIiM5ZTY5Y2YiLCIjOTMxZWEwIiwiIzE0ODgyNSIsIiNkYjA3MmYiLCIjMTExZThmIikKCiMgRXhhbXBsZSB1c2FnZSB3aXRoIHNwZWNpZmllZCBjb250cmFzdCBvcmRlcgpjb250cmFzdF9vcmRlciA8LSByZXYoYygiU05DQS1BNTNUIiwgIkdCQS1LTyIsICJQSU5LMS1LTyIsICJQUktOLUtPIiwgCiAgICAgICAgICAgICAgICAgICAgIklHU0Y5Qi1LTyIsIklOUFA1Ri1LTyIsICJTSDNHTDItS08iLCJJUDZLMi1LTyIpKQoKcCA8LSBjcmVhdGVfdXBzZXRfcGxvdChmaWx0ZXJlZF9ERVAsIGNvbnRyYXN0X29yZGVyLCBjb2xvcnMgPSByZXYoY29sb3JzKSwgdGV4dF9zY2FsZSA9IDEuNSkKcHJpbnQocCkKCmBgYAoKYGBge3J9CnBuZygiL1VzZXJzL3JoYWxlbmF0aG9tYXMvRG93bmxvYWRzL01vdmVfRGF0YS9EYXJrR2Vub21lUmVzdWx0L29taWNzL1Vwc2V0cGxvdEJyaWdodGFuZERhcmsucG5nIiwgd2lkdGggPSAxMDAwLCBoZWlnaHQgPSA1MDApCnAKZGV2Lm9mZigpCgpwZGYoIi9Vc2Vycy9yaGFsZW5hdGhvbWFzL0Rvd25sb2Fkcy9Nb3ZlX0RhdGEvRGFya0dlbm9tZVJlc3VsdC9vbWljcy9VcHNldHBsb3RCcmlnaHRhbmREYXJrLnBkZiIsIHdpZHRoID0gMTAsIGhlaWdodCA9IDUuNSkKcApkZXYub2ZmKCkKCmBgYAoKCgoKU2VlIHdoaWNoIGdlbmVzIG92ZXJsYXAgLSBmdW5jdGlvbiAKCmBgYHtyfQoKCiMgRnVuY3Rpb24gdG8gZXh0cmFjdCBvdmVybGFwcGluZyBhbmQgdW5pcXVlIGdlbmVzCmdldF9nZW5lX292ZXJsYXBfYW5kX3VuaXF1ZSA8LSBmdW5jdGlvbihmaWx0ZXJlZF9ERVAsIGNvbnRyYXN0X2xpc3QpIHsKICAKICAjIENoZWNrIGlmIGFsbCBjb250cmFzdHMgaW4gY29udHJhc3RfbGlzdCBleGlzdCBpbiBmaWx0ZXJlZF9ERVAKICBtaXNzaW5nX2NvbnRyYXN0cyA8LSBzZXRkaWZmKGNvbnRyYXN0X2xpc3QsIG5hbWVzKGZpbHRlcmVkX0RFUCkpCiAgaWYgKGxlbmd0aChtaXNzaW5nX2NvbnRyYXN0cykgPiAwKSB7CiAgICBzdG9wKHBhc3RlKCJUaGUgZm9sbG93aW5nIGNvbnRyYXN0cyBhcmUgbm90IGZvdW5kIGluIGZpbHRlcmVkX0RFUDoiLCBwYXN0ZShtaXNzaW5nX2NvbnRyYXN0cywgY29sbGFwc2UgPSAiLCAiKSkpCiAgfQoKICAjIEV4dHJhY3QgZ2VuZSBsaXN0cyBmb3IgZWFjaCBzcGVjaWZpZWQgY29udHJhc3QKICBnZW5lX2xpc3RzIDwtIGxhcHBseShjb250cmFzdF9saXN0LCBmdW5jdGlvbihjb250cmFzdCkgdW5pcXVlKGZpbHRlcmVkX0RFUFtbY29udHJhc3RdXSRTeW1ib2wpKQogIG5hbWVzKGdlbmVfbGlzdHMpIDwtIGNvbnRyYXN0X2xpc3QKCiAgIyBGaW5kIG92ZXJsYXBwaW5nIGdlbmVzIChjb21tb24gdG8gYWxsIGNvbnRyYXN0cyBpbiB0aGUgaW5wdXQgbGlzdCkKICBvdmVybGFwcGluZ19nZW5lcyA8LSBSZWR1Y2UoaW50ZXJzZWN0LCBnZW5lX2xpc3RzKQogIAogICMgRmluZCB1bmlxdWUgZ2VuZXMgZm9yIGVhY2ggY29udHJhc3QKICB1bmlxdWVfZ2VuZXMgPC0gbGFwcGx5KG5hbWVzKGdlbmVfbGlzdHMpLCBmdW5jdGlvbihjb250cmFzdCkgewogICAgIyBHZW5lcyBpbiB0aGUgY3VycmVudCBjb250cmFzdCBidXQgbm90IGluIGFueSBvdGhlciBjb250cmFzdCBmcm9tIHRoZSBsaXN0CiAgICBzZXRkaWZmKGdlbmVfbGlzdHNbW2NvbnRyYXN0XV0sIHVubGlzdChnZW5lX2xpc3RzW25hbWVzKGdlbmVfbGlzdHMpICE9IGNvbnRyYXN0XSkpCiAgfSkKICBuYW1lcyh1bmlxdWVfZ2VuZXMpIDwtIG5hbWVzKGdlbmVfbGlzdHMpCgogICMgQ3JlYXRlIGEgbGlzdCB0byBzdG9yZSB0aGUgcmVzdWx0cwogIHJlc3VsdF9saXN0IDwtIGxpc3QoCiAgICAiT3ZlcmxhcHBpbmcgR2VuZXMiID0gb3ZlcmxhcHBpbmdfZ2VuZXMsCiAgICAiVW5pcXVlIEdlbmVzIiA9IHVuaXF1ZV9nZW5lcwogICkKICAKICByZXR1cm4ocmVzdWx0X2xpc3QpCn0KCgoKCgoKIyBicmlnaHQgZ2Vub21lIG92ZXJsYXAKY29udHJhc3RfbGlzdCA8LSBjKCJTTkNBLUE1M1QiLCAiR0JBLUtPIiwgIlBJTksxLUtPIiwiUFJLTi1LTyIpICMgU3BlY2lmeSB0aGUgY29udHJhc3RzIG9mIGludGVyZXN0CgpyZXN1bHQuYnJpZ2h0IDwtIGdldF9nZW5lX292ZXJsYXBfYW5kX3VuaXF1ZShmaWx0ZXJlZF9ERVAsIGNvbnRyYXN0X2xpc3QpCgojIFByaW50IHJlc3VsdHMKcHJpbnQocmVzdWx0LmJyaWdodCRgT3ZlcmxhcHBpbmcgR2VuZXNgKSAjIEdlbmVzIGNvbW1vbiBhY3Jvc3MgYWxsIHNwZWNpZmllZCBjb250cmFzdHMKI3ByaW50KHJlc3VsdCRgVW5pcXVlIEdlbmVzYCkgIyBMaXN0IG9mIGdlbmVzIHVuaXF1ZSB0byBlYWNoIGNvbnRyYXN0CgoKCmBgYAoKRnVuY3Rpb24gaXNuJ3QgZXhhY3RseSBjb3JyZWN0IG5lZWQgdG8gZml4CgoKYGBge3J9CgpwaW5rLmRmIDwtIGZpbHRlcmVkX0RFUCRgUElOSzEtS09gCmRpbShwaW5rLmRmKQpwcmtuLmRmIDwtIGZpbHRlcmVkX0RFUCRgUFJLTi1LT2AKZGltKHBya24uZGYpCmludGVyc2VjdChwaW5rLmRmJEFjY2Vzc2lvbiwgcHJrbi5kZiRBY2Nlc3Npb24pCgoKYGBgCmBgYHtyfQojIGFwcGx5IHRvIGZpbHRlcmVkIGxpc3QKcmVndWxhdGlvbl9zdW1tYXJ5IDwtIHN1bW1hcml6ZV9yZWd1bGF0aW9ucyhmaWx0ZXJlZF9ERVApCnByaW50KHJlZ3VsYXRpb25fc3VtbWFyeSkKYGBgCgpgYGB7cn0KY29udHJhc3RfbGlzdCA8LSBjKCJTTkNBLUE1M1QiLCAiR0JBLUtPIiwgIlBJTksxLUtPIiwiUFJLTi1LTyIsIklHU0Y5Qi1LTyIsIklOUFA1Ri1LTyIsIklQNksyLUtPIiwiSUdTRjlCLUtPIiwgIklOUFA1Ri1LTyIsICJJUDZLMi1LTyIpICMgU3BlY2lmeSB0aGUgY29udHJhc3RzIG9mIGludGVyZXN0CgphbGwgPC0gZ2V0X2dlbmVfb3ZlcmxhcF9hbmRfdW5pcXVlKGZpbHRlcmVkX0RFUCwgY29udHJhc3RfbGlzdCkKcHJpbnQoYWxsJGBPdmVybGFwcGluZyBHZW5lc2ApCgoKCmBgYAoKCmBgYHtyfQpuYW1lcyhmaWx0ZXJlZF9ERVApCmBgYAoKYGBge3J9CmNvbnRyYXN0X2xpc3QgPC0gYygiR0JBLUtPIiwgIlBJTksxLUtPIikgIyBTcGVjaWZ5IHRoZSBjb250cmFzdHMgb2YgaW50ZXJlc3QKCmdiYS5waW5rMSA8LSBnZXRfZ2VuZV9vdmVybGFwX2FuZF91bmlxdWUoZmlsdGVyZWRfREVQLCBjb250cmFzdF9saXN0KQoKcHJpbnQoZ2JhLnBpbmsxKQogIyBHZW5lcyBjb21tb24gYWNyb3NzIGFsbCBzcGVjaWZpZWQgY29udHJhc3RzCiNwcmludChyZXN1bHQkYFVuaXF1ZSBHZW5lc2ApICMgTGlzdCBvZiBnZW5lcyB1bmlxdWUgdG8gZWFjaCBjb250cmFzdAoKYGBgCgoKCgpgYGB7cn0KIyBicmlnaHQgZ2Vub21lIG92ZXJsYXAKY29udHJhc3RfbGlzdCA8LSBjKCJJR1NGOUItS08iLCAiSU5QUDVGLUtPIiwiSVA2SzItS08iLCJTSDNHTDItS08iKSAjIFNwZWNpZnkgdGhlIGNvbnRyYXN0cyBvZiBpbnRlcmVzdAoKcmVzdWx0LmRhcmsgPC0gZ2V0X2dlbmVfb3ZlcmxhcF9hbmRfdW5pcXVlKGZpbHRlcmVkX0RFUCwgY29udHJhc3RfbGlzdCkKCiMgUHJpbnQgcmVzdWx0cwpwcmludChyZXN1bHQuZGFyayRgT3ZlcmxhcHBpbmcgR2VuZXNgKSAjIEdlbmVzIGNvbW1vbiBhY3Jvc3MgYWxsIHNwZWNpZmllZCBjb250cmFzdHMKI3ByaW50KHJlc3VsdC5kYXJrJGBVbmlxdWUgR2VuZXNgKSAjIExpc3Qgb2YgZ2VuZXMgdW5pcXVlIHRvIGVhY2ggY29udHJhc3QKCgpgYGAKCkxvb2sgYXQgb3ZlcmxhcCBpbiBjb250cmFzdHMgdGhhdCBhbHNvIGhhdmUgdGFyZ2V0ZWQgcGF0aHdheXMgY2hhbmdlcyB0aGF0IG1hdGNoCgoKYGBge3J9CgojIFBSS04gS08sIElHU0Y5QiBhbmQgU0gzR0wyIGFsbCBhcmUgZG93biByZWd1bGF0ZWQgaW4gVEggKyBsZXZlbHMKY29udHJhc3RfbGlzdCA8LSBjKCJQUktOLUtPIiwiSUdTRjlCLUtPIiwiU0gzR0wyLUtPIikgIyBTcGVjaWZ5IHRoZSBjb250cmFzdHMgb2YgaW50ZXJlc3QKCnJlc3VsdC5USGRvd24gPC0gZ2V0X2dlbmVfb3ZlcmxhcF9hbmRfdW5pcXVlKGZpbHRlcmVkX0RFUCwgY29udHJhc3RfbGlzdCkKCiMgUHJpbnQgcmVzdWx0cwpwcmludChyZXN1bHQuVEhkb3duJGBPdmVybGFwcGluZyBHZW5lc2ApICMgR2VuZXMgY29tbW9uIGFjcm9zcyBhbGwgc3BlY2lmaWVkIGNvbnRyYXN0cwoKCmBgYAoKYGBge3J9CgpkZi5sb25nIDwtIHByb3RlaW5fenNjb3JlKGRhdGEgPSBkZiwKICBwcm90ZWlucyA9IHJlc3VsdC5USGRvd24kYE92ZXJsYXBwaW5nIEdlbmVzYCwgIyBFeGFtcGxlIHByb3RlaW4gbmFtZXMKICBzYW1wbGVfcGF0dGVybnMgPSBjKCJDb250cm9sIiwiUFJLTi5LTyIsIklHU0Y5QiIgLCJTSDNHTDIuS08iKSwgZ3JvdXBfbWVhbnMgPSBUUlVFKSAKICAKbWF4KGRmLmxvbmckQWJ1bmRhbmNlKQptaW4oZGYubG9uZyRBYnVuZGFuY2UpCgpwbG90X3Byb3RlaW5faGVhdG1hcF96c2NvcmUoCiAgZGF0YSA9IGRmLAogIHByb3RlaW5zID0gcmVzdWx0LlRIZG93biRgT3ZlcmxhcHBpbmcgR2VuZXNgLCAjIEV4YW1wbGUgcHJvdGVpbiBuYW1lcwogIHNhbXBsZV9wYXR0ZXJucyA9IGMoIkNvbnRyb2wiLCJQUktOLktPIiwiSUdTRjlCLktPIiAsIlNIM0dMMi5LTyIpLAogIGNvbG9ycyA9IGMoInNub3ciLCAibGlnaHRnb2xkZW5yb2QxIiwgImdvbGQxIiwgImRhcmtvcmFuZ2UxIiwicmVkIiwgInJlZDIiLCAiZmlyZWJyaWNrNCIpLAogIHNjYWxlX3ZhbHVlcyA9IGMoLTEsIC0wLjUsLTAuMjUsIDAsIDEsIDIuNSwgNC41KSwgIyBBZGp1c3QgYmFzZWQgb24geW91ciBkYXRhIHJhbmdlCiAgZ3JvdXBfbWVhbnMgPSBUUlVFLCMgU2V0IHRvIEZBTFNFIGlmIHlvdSB3YW50IGluZGl2aWR1YWwgc2FtcGxlcwogICB0aWxlX3dpZHRoID0gMC4yNQopIAoKCgoKYGBgCgpGdW5jdGlvbiB0byBwbG90IGdyb3VwZWQgYnkgZXhwcmVzc2lvbgoKCmBgYHtyfQojIExvYWQgcmVxdWlyZWQgbGlicmFyaWVzCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkodGlkeXIpCmxpYnJhcnkocGhlYXRtYXApCgojIEZ1bmN0aW9uIHRvIHBsb3QgaGVhdG1hcCBvZiByZWxhdGl2ZSBhYnVuZGFuY2Ugd2l0aCBaLXNjb3JlcyBhbmQgY2x1c3RlcmluZwpwbG90X2NsdXN0ZXJlZF9wcm90ZWluX2hlYXRtYXBfenNjb3JlIDwtIGZ1bmN0aW9uKGRhdGEsIHByb3RlaW5zLCBzYW1wbGVfcGF0dGVybnMsIGNvbG9ycywgc2NhbGVfdmFsdWVzLCBuYV9jb2xvciA9ICJncmV5IiwgZ3JvdXBfbWVhbnMgPSBGQUxTRSkgewogICMgRmlsdGVyIHRoZSBkYXRhIGZvciBzZWxlY3RlZCBwcm90ZWlucwogIGRhdGFfZmlsdGVyZWQgPC0gZGF0YSAlPiUKICAgIGZpbHRlcihTeW1ib2wgJWluJSBwcm90ZWlucykKICAKICAjIFNldCB0aGUgb3JkZXIgb2YgdGhlIFN5bWJvbCBmYWN0b3IgYmFzZWQgb24gdGhlIGlucHV0IHZlY3RvciAncHJvdGVpbnMnCiAgZGF0YV9maWx0ZXJlZCRTeW1ib2wgPC0gZmFjdG9yKGRhdGFfZmlsdGVyZWQkU3ltYm9sLCBsZXZlbHMgPSBwcm90ZWlucykKCiAgIyBJZGVudGlmeSBzYW1wbGUgY29sdW1ucyBtYXRjaGluZyBwYXR0ZXJucwogIHNhbXBsZV9jb2x1bW5zIDwtIGNvbG5hbWVzKGRhdGFfZmlsdGVyZWQpW3NhcHBseShjb2xuYW1lcyhkYXRhX2ZpbHRlcmVkKSwgZnVuY3Rpb24oY29sX25hbWUpIHsKICAgIGFueShzYXBwbHkoc2FtcGxlX3BhdHRlcm5zLCBmdW5jdGlvbihwKSBncmVwbChwLCBjb2xfbmFtZSkpKQogIH0pXQoKICAjIERlYnVnOiBDaGVjayBjb250ZW50cyBvZiBzYW1wbGVfY29sdW1ucwogIHByaW50KHBhc3RlKCJTYW1wbGUgY29sdW1ucyBzZWxlY3RlZDoiLCBwYXN0ZShzYW1wbGVfY29sdW1ucywgY29sbGFwc2UgPSAiLCAiKSkpCgogICMgQ2hlY2sgaWYgc2FtcGxlX2NvbHVtbnMgaGFzIHZhbGlkIGVudHJpZXMKICBpZiAobGVuZ3RoKHNhbXBsZV9jb2x1bW5zKSA9PSAwKSB7CiAgICBzdG9wKCJObyBzYW1wbGUgY29sdW1ucyBtYXRjaGVkIHRoZSBwYXR0ZXJucyBwcm92aWRlZC4iKQogIH0KCiAgIyBTZWxlY3Qgb25seSBjb2x1bW5zIG1hdGNoaW5nIHNhbXBsZSBwYXR0ZXJucyBhbmQgdGhlIFN5bWJvbCBjb2x1bW4KICBkYXRhX2ZpbHRlcmVkIDwtIGRhdGFfZmlsdGVyZWQgJT4lCiAgICBkcGx5cjo6c2VsZWN0KFN5bWJvbCwgYWxsX29mKHNhbXBsZV9jb2x1bW5zKSkKCiAgIyBSZW1vdmUgcm93cyB3aGVyZSBhbGwgdmFsdWVzIGFyZSBOQSAoZXhjbHVkaW5nIHRoZSBTeW1ib2wgY29sdW1uKQogIGRhdGFfZmlsdGVyZWQgPC0gZGF0YV9maWx0ZXJlZCAlPiUKICAgIGZpbHRlcihyb3dTdW1zKGlzLm5hKGRwbHlyOjpzZWxlY3QoLiwgLVN5bWJvbCkpKSA8IGxlbmd0aChzYW1wbGVfY29sdW1ucykpCgogIGlmIChncm91cF9tZWFucykgewogICAgIyBHcm91cCBzYW1wbGVzIGJ5IHRoZSBiYXNlIG5hbWUgYW5kIGNhbGN1bGF0ZSBtZWFuCiAgICBzYW1wbGVfYmFzZSA8LSBnc3ViKCJcXC5cXGQrJCIsICIiLCBjb2xuYW1lcyhkYXRhX2ZpbHRlcmVkKVstMV0pCiAgICBkYXRhX2dyb3VwZWQgPC0gZGF0YV9maWx0ZXJlZCAlPiUKICAgICAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAtU3ltYm9sLCBuYW1lc190byA9ICJTYW1wbGUiLCB2YWx1ZXNfdG8gPSAiQWJ1bmRhbmNlIikgJT4lCiAgICAgIG11dGF0ZShTYW1wbGVCYXNlID0gZ3N1YigiXFwuXFxkKyQiLCAiIiwgU2FtcGxlKSkgJT4lCiAgICAgIGdyb3VwX2J5KFN5bWJvbCwgU2FtcGxlQmFzZSkgJT4lCiAgICAgIHN1bW1hcml6ZShBYnVuZGFuY2UgPSBtZWFuKEFidW5kYW5jZSwgbmEucm0gPSBUUlVFKSwgLmdyb3VwcyA9ICdkcm9wJykgJT4lCiAgICAgIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBTYW1wbGVCYXNlLCB2YWx1ZXNfZnJvbSA9IEFidW5kYW5jZSkKCiAgICAjIENhbGN1bGF0ZSBaLXNjb3JlcwogICAgZGF0YV96c2NvcmUgPC0gZGF0YV9ncm91cGVkICU+JQogICAgICBtdXRhdGUoYWNyb3NzKC1TeW1ib2wsIH4gc2NhbGUoLilbLCAxXSwgLm5hbWVzID0gIntjb2x9IikpCgogICAgIyBDb252ZXJ0IGRhdGEgdG8gbWF0cml4IGZvcm0gZm9yIHBoZWF0bWFwCiAgICBkYXRhX21hdHJpeCA8LSBhcy5tYXRyaXgoZGF0YV96c2NvcmVbLC0xXSkgICMgRXhjbHVkZSB0aGUgU3ltYm9sIGNvbHVtbiBmcm9tIG1hdHJpeCBjb252ZXJzaW9uCiAgICByb3duYW1lcyhkYXRhX21hdHJpeCkgPC0gZGF0YV96c2NvcmUkU3ltYm9sICMgU2V0IHJvdyBuYW1lcyB0byB0aGUgU3ltYm9sIGNvbHVtbgogIH0gZWxzZSB7CiAgICAjIENhbGN1bGF0ZSBaLXNjb3JlcyBmb3IgZWFjaCBwcm90ZWluIGFjcm9zcyB0aGUgc2VsZWN0ZWQgc2FtcGxlcwogICAgZGF0YV96c2NvcmUgPC0gZGF0YV9maWx0ZXJlZCAlPiUKICAgICAgbXV0YXRlKGFjcm9zcyhhbGxfb2Yoc2FtcGxlX2NvbHVtbnMpLCB+IHNjYWxlKC4pWywgMV0sIC5uYW1lcyA9ICJ7Y29sfSIpKQoKICAgICMgQ29udmVydCBkYXRhIHRvIG1hdHJpeCBmb3JtIGZvciBwaGVhdG1hcAogICAgZGF0YV9tYXRyaXggPC0gYXMubWF0cml4KGRhdGFfenNjb3JlWywtMV0pICAjIEV4Y2x1ZGUgdGhlIFN5bWJvbCBjb2x1bW4gZnJvbSBtYXRyaXggY29udmVyc2lvbgogICAgcm93bmFtZXMoZGF0YV9tYXRyaXgpIDwtIGRhdGFfenNjb3JlJFN5bWJvbCAjIFNldCByb3cgbmFtZXMgdG8gdGhlIFN5bWJvbCBjb2x1bW4KICB9CgogICMgQ3JlYXRlIHRoZSBoZWF0bWFwIHdpdGggaGllcmFyY2hpY2FsIGNsdXN0ZXJpbmcKICBwaGVhdG1hcCgKICAgIGRhdGFfbWF0cml4LAogICAgY2x1c3Rlcl9yb3dzID0gVFJVRSwKICAgIGNsdXN0ZXJfY29scyA9IFRSVUUsCiAgICBjb2xvciA9IGNvbG9yUmFtcFBhbGV0dGUoY29sb3JzKSgxMDApLAogICAgbmFfY29sID0gbmFfY29sb3IsCiAgICBtYWluID0gIkNsdXN0ZXJlZCBQcm90ZWluIEFidW5kYW5jZSBIZWF0bWFwIChaLVNjb3JlKSIKICApCn0KCiMgRXhhbXBsZSB1c2FnZQpoZWF0bWFwX3Bsb3QgPC0gcGxvdF9jbHVzdGVyZWRfcHJvdGVpbl9oZWF0bWFwX3pzY29yZSgKICBkYXRhID0gZGYsCiAgcHJvdGVpbnMgPSByZXN1bHQuVEhkb3duJGBPdmVybGFwcGluZyBHZW5lc2AsICMgRXhhbXBsZSBwcm90ZWluIG5hbWVzCiAgc2FtcGxlX3BhdHRlcm5zID0gYygiQ29udHJvbCIsICJJR1NGOUIuS08iLCAiU0gzR0wyLktPIiksCiAgY29sb3JzID0gYygic25vdyIsICJsaWdodGdvbGRlbnJvZDEiLCAiZ29sZDEiLCAiZGFya29yYW5nZTEiLCAicmVkMiIsICJmaXJlYnJpY2s0IiksCiAgc2NhbGVfdmFsdWVzID1jKC0xLCAtMC41LC0wLjI1LCAwLCAxLCAyLjUsIDQuNSksICMgQWRqdXN0IGJhc2VkIG9uIHlvdXIgZGF0YSByYW5nZQogIGdyb3VwX21lYW5zID0gRkFMU0UsICMgU2V0IHRvIEZBTFNFIGlmIHlvdSB3YW50IGluZGl2aWR1YWwgc2FtcGxlcwogICkgCgoKCmBgYApgYGB7cn0KIyBMb2FkIHJlcXVpcmVkIGxpYnJhcmllcwpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KHBoZWF0bWFwKQoKIyBGdW5jdGlvbiB0byBwbG90IGhlYXRtYXAgb2YgcmVsYXRpdmUgYWJ1bmRhbmNlIHdpdGggWi1zY29yZXMgYW5kIGNsdXN0ZXJpbmcKcGxvdF9jbHVzdGVyZWRfcHJvdGVpbl9oZWF0bWFwX3pzY29yZSA8LSBmdW5jdGlvbihkYXRhLCBwcm90ZWlucywgc2FtcGxlX3BhdHRlcm5zLCBjb2xvcnMsIHNjYWxlX3ZhbHVlcywgbmFfY29sb3IgPSAiZ3JleSIsIGdyb3VwX21lYW5zID0gRkFMU0UsIGNlbGxfd2lkdGggPSAxMCwgY2VsbF9oZWlnaHQgPSAxMCkgewogICMgRmlsdGVyIHRoZSBkYXRhIGZvciBzZWxlY3RlZCBwcm90ZWlucwogIGRhdGFfZmlsdGVyZWQgPC0gZGF0YSAlPiUKICAgIGZpbHRlcihTeW1ib2wgJWluJSBwcm90ZWlucykKICAKICAjIFNldCB0aGUgb3JkZXIgb2YgdGhlIFN5bWJvbCBmYWN0b3IgYmFzZWQgb24gdGhlIGlucHV0IHZlY3RvciAncHJvdGVpbnMnCiAgZGF0YV9maWx0ZXJlZCRTeW1ib2wgPC0gZmFjdG9yKGRhdGFfZmlsdGVyZWQkU3ltYm9sLCBsZXZlbHMgPSBwcm90ZWlucykKCiAgIyBJZGVudGlmeSBzYW1wbGUgY29sdW1ucyBtYXRjaGluZyBwYXR0ZXJucwogIHNhbXBsZV9jb2x1bW5zIDwtIGNvbG5hbWVzKGRhdGFfZmlsdGVyZWQpW3NhcHBseShjb2xuYW1lcyhkYXRhX2ZpbHRlcmVkKSwgZnVuY3Rpb24oY29sX25hbWUpIHsKICAgIGFueShzYXBwbHkoc2FtcGxlX3BhdHRlcm5zLCBmdW5jdGlvbihwKSBncmVwbChwLCBjb2xfbmFtZSkpKQogIH0pXQoKICAjIERlYnVnOiBDaGVjayBjb250ZW50cyBvZiBzYW1wbGVfY29sdW1ucwogIHByaW50KHBhc3RlKCJTYW1wbGUgY29sdW1ucyBzZWxlY3RlZDoiLCBwYXN0ZShzYW1wbGVfY29sdW1ucywgY29sbGFwc2UgPSAiLCAiKSkpCgogICMgQ2hlY2sgaWYgc2FtcGxlX2NvbHVtbnMgaGFzIHZhbGlkIGVudHJpZXMKICBpZiAobGVuZ3RoKHNhbXBsZV9jb2x1bW5zKSA9PSAwKSB7CiAgICBzdG9wKCJObyBzYW1wbGUgY29sdW1ucyBtYXRjaGVkIHRoZSBwYXR0ZXJucyBwcm92aWRlZC4iKQogIH0KCiAgIyBTZWxlY3Qgb25seSBjb2x1bW5zIG1hdGNoaW5nIHNhbXBsZSBwYXR0ZXJucyBhbmQgdGhlIFN5bWJvbCBjb2x1bW4KICBkYXRhX2ZpbHRlcmVkIDwtIGRhdGFfZmlsdGVyZWQgJT4lCiAgICBkcGx5cjo6c2VsZWN0KFN5bWJvbCwgYWxsX29mKHNhbXBsZV9jb2x1bW5zKSkKCiAgIyBSZW1vdmUgcm93cyB3aGVyZSBhbGwgdmFsdWVzIGFyZSBOQSAoZXhjbHVkaW5nIHRoZSBTeW1ib2wgY29sdW1uKQogIGRhdGFfZmlsdGVyZWQgPC0gZGF0YV9maWx0ZXJlZCAlPiUKICAgIGZpbHRlcihyb3dTdW1zKGlzLm5hKGRwbHlyOjpzZWxlY3QoLiwgLVN5bWJvbCkpKSA8IGxlbmd0aChzYW1wbGVfY29sdW1ucykpCgogIGlmIChncm91cF9tZWFucykgewogICAgIyBHcm91cCBzYW1wbGVzIGJ5IHRoZSBiYXNlIG5hbWUgYW5kIGNhbGN1bGF0ZSBtZWFuCiAgICBzYW1wbGVfYmFzZSA8LSBnc3ViKCJcXC5cXGQrJCIsICIiLCBjb2xuYW1lcyhkYXRhX2ZpbHRlcmVkKVstMV0pCiAgICBkYXRhX2dyb3VwZWQgPC0gZGF0YV9maWx0ZXJlZCAlPiUKICAgICAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAtU3ltYm9sLCBuYW1lc190byA9ICJTYW1wbGUiLCB2YWx1ZXNfdG8gPSAiQWJ1bmRhbmNlIikgJT4lCiAgICAgIG11dGF0ZShTYW1wbGVCYXNlID0gZ3N1YigiXFwuXFxkKyQiLCAiIiwgU2FtcGxlKSkgJT4lCiAgICAgIGdyb3VwX2J5KFN5bWJvbCwgU2FtcGxlQmFzZSkgJT4lCiAgICAgIHN1bW1hcml6ZShBYnVuZGFuY2UgPSBtZWFuKEFidW5kYW5jZSwgbmEucm0gPSBUUlVFKSwgLmdyb3VwcyA9ICdkcm9wJykgJT4lCiAgICAgIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBTYW1wbGVCYXNlLCB2YWx1ZXNfZnJvbSA9IEFidW5kYW5jZSkKCiAgICAjIENhbGN1bGF0ZSBaLXNjb3JlcwogICAgZGF0YV96c2NvcmUgPC0gZGF0YV9ncm91cGVkICU+JQogICAgICBtdXRhdGUoYWNyb3NzKC1TeW1ib2wsIH4gc2NhbGUoLilbLCAxXSwgLm5hbWVzID0gIntjb2x9IikpCgogICAgIyBDb252ZXJ0IGRhdGEgdG8gbWF0cml4IGZvcm0gZm9yIHBoZWF0bWFwCiAgICBkYXRhX21hdHJpeCA8LSBhcy5tYXRyaXgoZGF0YV96c2NvcmVbLC0xXSkgICMgRXhjbHVkZSB0aGUgU3ltYm9sIGNvbHVtbiBmcm9tIG1hdHJpeCBjb252ZXJzaW9uCiAgICByb3duYW1lcyhkYXRhX21hdHJpeCkgPC0gZGF0YV96c2NvcmUkU3ltYm9sICMgU2V0IHJvdyBuYW1lcyB0byB0aGUgU3ltYm9sIGNvbHVtbgogIH0gZWxzZSB7CiAgICAjIENhbGN1bGF0ZSBaLXNjb3JlcyBmb3IgZWFjaCBwcm90ZWluIGFjcm9zcyB0aGUgc2VsZWN0ZWQgc2FtcGxlcwogICAgZGF0YV96c2NvcmUgPC0gZGF0YV9maWx0ZXJlZCAlPiUKICAgICAgbXV0YXRlKGFjcm9zcyhhbGxfb2Yoc2FtcGxlX2NvbHVtbnMpLCB+IHNjYWxlKC4pWywgMV0sIC5uYW1lcyA9ICJ7Y29sfSIpKQoKICAgICMgQ29udmVydCBkYXRhIHRvIG1hdHJpeCBmb3JtIGZvciBwaGVhdG1hcAogICAgZGF0YV9tYXRyaXggPC0gYXMubWF0cml4KGRhdGFfenNjb3JlWywtMV0pICAjIEV4Y2x1ZGUgdGhlIFN5bWJvbCBjb2x1bW4gZnJvbSBtYXRyaXggY29udmVyc2lvbgogICAgcm93bmFtZXMoZGF0YV9tYXRyaXgpIDwtIGRhdGFfenNjb3JlJFN5bWJvbCAjIFNldCByb3cgbmFtZXMgdG8gdGhlIFN5bWJvbCBjb2x1bW4KICB9CgogICMgQ3JlYXRlIHRoZSBoZWF0bWFwIHdpdGggaGllcmFyY2hpY2FsIGNsdXN0ZXJpbmcKICBwaGVhdG1hcCgKICAgIGRhdGFfbWF0cml4LAogICAgY2x1c3Rlcl9yb3dzID0gVFJVRSwKICAgIGNsdXN0ZXJfY29scyA9IFRSVUUsCiAgICBjb2xvciA9IGNvbG9yUmFtcFBhbGV0dGUoY29sb3JzKSgxMDApLAogICAgbmFfY29sID0gbmFfY29sb3IsCiAgICBtYWluID0gIkNsdXN0ZXJlZCBQcm90ZWluIEFidW5kYW5jZSBIZWF0bWFwIChaLVNjb3JlKSIsCiAgICBjZWxsd2lkdGggPSBjZWxsX3dpZHRoLCAgICMgQWRqdXN0IGNlbGwgd2lkdGgKICAgIGNlbGxoZWlnaHQgPSBjZWxsX2hlaWdodCAgIyBBZGp1c3QgY2VsbCBoZWlnaHQKICApCn0KCiMgRXhhbXBsZSB1c2FnZQpoZWF0bWFwX3Bsb3QgPC0gcGxvdF9jbHVzdGVyZWRfcHJvdGVpbl9oZWF0bWFwX3pzY29yZSgKICBkYXRhID0gZGYsCiAgcHJvdGVpbnMgPSByZXN1bHQuVEhkb3duJGBPdmVybGFwcGluZyBHZW5lc2AsICMgRXhhbXBsZSBwcm90ZWluIG5hbWVzCiAgc2FtcGxlX3BhdHRlcm5zID0gYygiQ29udHJvbCIsICJJR1NGOUIuS08iLCAiU0gzR0wyLktPIiksCiAgY29sb3JzID0gYygic25vdyIsICJsaWdodGdvbGRlbnJvZDEiLCAiZ29sZDEiLCAiZGFya29yYW5nZTEiLCAicmVkMiIsICJmaXJlYnJpY2s0IiksCiAgc2NhbGVfdmFsdWVzID0gYygtMSwgLTAuNSwtMC4yNSwgMCwgMSwgMi41LCA0LjUpLCAjIEFkanVzdCBiYXNlZCBvbiB5b3VyIGRhdGEgcmFuZ2UKICBncm91cF9tZWFucyA9IFRSVUUsICMgU2V0IHRvIEZBTFNFIGlmIHlvdSB3YW50IGluZGl2aWR1YWwgc2FtcGxlcwogIGNlbGxfd2lkdGggPSAyMCwgIyBDb250cm9sIGNvbHVtbiB3aWR0aAogIGNlbGxfaGVpZ2h0ID0gMTAgIyBDb250cm9sIHJvdyBoZWlnaHQKKQoKIyBFeGFtcGxlIHVzYWdlCmhlYXRtYXBfcGxvdCA8LSBwbG90X2NsdXN0ZXJlZF9wcm90ZWluX2hlYXRtYXBfenNjb3JlKAogIGRhdGEgPSBkZiwKICBwcm90ZWlucyA9IHJlc3VsdC5USGRvd24kYE92ZXJsYXBwaW5nIEdlbmVzYCwgICMgRXhhbXBsZSBwcm90ZWluIG5hbWVzCiAgc2FtcGxlX3BhdHRlcm5zID0gYygiQ29udHJvbCIsICJJR1NGOUIuS08iLCAiU0gzR0wyLktPIiksCiAgY29sb3JzID0gYygic25vdyIsICJsaWdodGdvbGRlbnJvZDEiLCAiZ29sZDEiLCAiZGFya29yYW5nZTEiLCAicmVkMiIsICJmaXJlYnJpY2s0IiksCiAgc2NhbGVfdmFsdWVzID0gYygtMSwgLTAuNSwtMC4yNSwgMCwgMSwgMi41LCA0LjUpLCAjIEFkanVzdCBiYXNlZCBvbiB5b3VyIGRhdGEgcmFuZ2UKICBncm91cF9tZWFucyA9IEZBTFNFLCAjIFNldCB0byBGQUxTRSBpZiB5b3Ugd2FudCBpbmRpdmlkdWFsIHNhbXBsZXMKICBjZWxsX3dpZHRoID0gMjAsICMgQ29udHJvbCBjb2x1bW4gd2lkdGgKICBjZWxsX2hlaWdodCA9IDEwICMgQ29udHJvbCByb3cgaGVpZ2h0CikKCgoKYGBgCgoKYGBge3J9CmNvbnRyYXN0X2xpc3QgPC0gYygiUFJLTi1LTyIsIklHU0Y5Qi1LTyIsIlNIM0dMMi1LTyIsICJJUDZLMi1LTyIpICMgU3BlY2lmeSB0aGUgY29udHJhc3RzIG9mIGludGVyZXN0CgpyZXN1bHQuR0Nhc2Vkb3duIDwtIGdldF9nZW5lX292ZXJsYXBfYW5kX3VuaXF1ZShmaWx0ZXJlZF9ERVAsIGNvbnRyYXN0X2xpc3QpCgojIFByaW50IHJlc3VsdHMKcHJpbnQocmVzdWx0LkdDYXNlZG93biRgT3ZlcmxhcHBpbmcgR2VuZXNgKSAjIEdlbmVzIGNvbW1vbiBhY3Jvc3MgYWxsIHNwZWNpZmllZCBjb250cmFzdHMKCmBgYAoKCgpPdmVybGFwcGluZyBsaXN0IG9mIHRoZSBnZW5vdHlwZXMgd2l0aCBHQ0FzZSBhY3Rpdml0eSBkb3duOiBHQkEtS08sIFBSTkstS08sIElOUFA1Ri1LTywgU0gzR0wyLUtPLCBJUDZLMi1LTwoKYGBge3J9CgojY29sbmFtZXMoZGYpCgpkZi5sb25nIDwtIHByb3RlaW5fenNjb3JlKGRhdGEgPSBkZiwKICBwcm90ZWlucyA9IHJlc3VsdC5HQ2FzZWRvd24kYE92ZXJsYXBwaW5nIEdlbmVzYCwgIyBFeGFtcGxlIHByb3RlaW4gbmFtZXMKICBzYW1wbGVfcGF0dGVybnMgPSBjKCJDb250cm9sIiwiUFJLTi5LTyIsIklHU0Y5QiIgLCJTSDNHTDIuS08iLCJJUDZLMi5LTyIpLCBncm91cF9tZWFucyA9IFRSVUUpIAogIAptYXgoZGYubG9uZyRBYnVuZGFuY2UpCm1pbihkZi5sb25nJEFidW5kYW5jZSkKCgojIEV4YW1wbGUgdXNhZ2UKaGVhdG1hcF9wbG90IDwtIHBsb3RfY2x1c3RlcmVkX3Byb3RlaW5faGVhdG1hcF96c2NvcmUoCiAgZGF0YSA9IGRmLAogIHByb3RlaW5zID0gcmVzdWx0LkdDYXNlZG93biRgT3ZlcmxhcHBpbmcgR2VuZXNgLCAjIEV4YW1wbGUgcHJvdGVpbiBuYW1lcwogIHNhbXBsZV9wYXR0ZXJucyA9IGMoIkNvbnRyb2wiLCAiSUdTRjlCLktPIiwgIlNIM0dMMi5LTyIsIklQNksyLktPIiksCiAgY29sb3JzID0gYygic25vdyIsICJsaWdodGdvbGRlbnJvZDEiLCAiZ29sZDEiLCAiZGFya29yYW5nZTEiLCAicmVkMiIsICJmaXJlYnJpY2s0IiksCiAgc2NhbGVfdmFsdWVzID0gYygtMS41LCAtMSwtMC41LCAwLCAxLDIsIDIuNSksICMgQWRqdXN0IGJhc2VkIG9uIHlvdXIgZGF0YSByYW5nZQogIGdyb3VwX21lYW5zID0gVFJVRSwgIyBTZXQgdG8gRkFMU0UgaWYgeW91IHdhbnQgaW5kaXZpZHVhbCBzYW1wbGVzCiAgY2VsbF93aWR0aCA9IDIwLCAjIENvbnRyb2wgY29sdW1uIHdpZHRoCiAgY2VsbF9oZWlnaHQgPSAxMCAjIENvbnRyb2wgcm93IGhlaWdodAopCgojIEV4YW1wbGUgdXNhZ2UKaGVhdG1hcF9wbG90IDwtIHBsb3RfY2x1c3RlcmVkX3Byb3RlaW5faGVhdG1hcF96c2NvcmUoCiAgZGF0YSA9IGRmLAogIHByb3RlaW5zID0gcmVzdWx0LkdDYXNlZG93biRgT3ZlcmxhcHBpbmcgR2VuZXNgLCAgIyBFeGFtcGxlIHByb3RlaW4gbmFtZXMKICBzYW1wbGVfcGF0dGVybnMgPSBjKCJDb250cm9sIiwgIklHU0Y5Qi5LTyIsICJTSDNHTDIuS08iLCJJUDZLMi5LTyIpLAogIGNvbG9ycyA9IGMoInNub3ciLCAibGlnaHRnb2xkZW5yb2QxIiwgImdvbGQxIiwgImRhcmtvcmFuZ2UxIiwgInJlZDIiLCAiZmlyZWJyaWNrNCIpLAogIHNjYWxlX3ZhbHVlcyA9IGMoLTEuNSwgLTEsLTAuNSwgMCwgMSwgMiwgMi41KSwgIyBBZGp1c3QgYmFzZWQgb24geW91ciBkYXRhIHJhbmdlCiAgZ3JvdXBfbWVhbnMgPSBGQUxTRSwgIyBTZXQgdG8gRkFMU0UgaWYgeW91IHdhbnQgaW5kaXZpZHVhbCBzYW1wbGVzCiAgY2VsbF93aWR0aCA9IDIwLCAjIENvbnRyb2wgY29sdW1uIHdpZHRoCiAgY2VsbF9oZWlnaHQgPSAxMCAjIENvbnRyb2wgcm93IGhlaWdodAopCgoKCmBgYAoKYGBge3J9CmNvbnRyYXN0X2xpc3QgPC0gYygiSU5QUDVGLUtPIiwiU0gzR0wyLUtPIikgIyBTcGVjaWZ5IHRoZSBjb250cmFzdHMgb2YgaW50ZXJlc3QKCnJlc3VsdC5seXNvIDwtIGdldF9nZW5lX292ZXJsYXBfYW5kX3VuaXF1ZShmaWx0ZXJlZF9ERVAsIGNvbnRyYXN0X2xpc3QpCgojIFByaW50IHJlc3VsdHMKcHJpbnQocmVzdWx0Lmx5c28kYE92ZXJsYXBwaW5nIEdlbmVzYCkgIyBHZW5lcyBjb21tb24gYWNyb3NzIGFsbCBzcGVjaWZpZWQgY29udHJhc3RzCgpkZi5sb25nIDwtIHByb3RlaW5fenNjb3JlKGRhdGEgPSBkZiwKICBwcm90ZWlucyA9IHJlc3VsdC5seXNvJGBPdmVybGFwcGluZyBHZW5lc2AsICMgRXhhbXBsZSBwcm90ZWluIG5hbWVzCiAgc2FtcGxlX3BhdHRlcm5zID0gYygiQ29udHJvbCIsIklOUFA1RiIgLCJTSDNHTDIiKSwgZ3JvdXBfbWVhbnMgPSBUUlVFKSAKICAKbWF4KGRmLmxvbmckQWJ1bmRhbmNlKQptaW4oZGYubG9uZyRBYnVuZGFuY2UpCgpwcm8ubGlzdCA8LSByZXN1bHQubHlzbyRgT3ZlcmxhcHBpbmcgR2VuZXNgCgojIGxpc3QgaXMgdG9vIGxvbmcKCgoKIyBFeGFtcGxlIHVzYWdlCmhlYXRtYXBfcGxvdCA8LSBwbG90X2NsdXN0ZXJlZF9wcm90ZWluX2hlYXRtYXBfenNjb3JlKAogIGRhdGEgPSBkZiwKICBwcm90ZWlucyA9IHByby5saXN0LCAjIEV4YW1wbGUgcHJvdGVpbiBuYW1lcwogIHNhbXBsZV9wYXR0ZXJucyA9IGMoIkNvbnRyb2wiLCAiSUdTRjlCLktPIiwgIlNIM0dMMi5LTyIsIklQNksyLktPIiksCiAgY29sb3JzID0gYygic25vdyIsICJsaWdodGdvbGRlbnJvZDEiLCAiZ29sZDEiLCAiZGFya29yYW5nZTEiLCAicmVkMiIsICJmaXJlYnJpY2s0IiksCiAgc2NhbGVfdmFsdWVzID0gYygtMC41LC0wLjI1LCAwLCAyLjUsIDQuNSwgNi41KSwgIyBBZGp1c3QgYmFzZWQgb24geW91ciBkYXRhIHJhbmdlCiAgZ3JvdXBfbWVhbnMgPSBUUlVFLCAjIFNldCB0byBGQUxTRSBpZiB5b3Ugd2FudCBpbmRpdmlkdWFsIHNhbXBsZXMKICBjZWxsX3dpZHRoID0gMjAsICMgQ29udHJvbCBjb2x1bW4gd2lkdGgKICBjZWxsX2hlaWdodCA9IDEwICMgQ29udHJvbCByb3cgaGVpZ2h0CikKCiMgRXhhbXBsZSB1c2FnZQpoZWF0bWFwX3Bsb3QgPC0gcGxvdF9jbHVzdGVyZWRfcHJvdGVpbl9oZWF0bWFwX3pzY29yZSgKICBkYXRhID0gZGYsCiAgcHJvdGVpbnMgPSBwcm8ubGlzdCwgICMgRXhhbXBsZSBwcm90ZWluIG5hbWVzCiAgc2FtcGxlX3BhdHRlcm5zID0gYygiQ29udHJvbCIsICJJR1NGOUIuS08iLCAiU0gzR0wyLktPIiwiSVA2SzIuS08iKSwKICBjb2xvcnMgPSBjKCJzbm93IiwgImxpZ2h0Z29sZGVucm9kMSIsICJnb2xkMSIsICJkYXJrb3JhbmdlMSIsICJyZWQyIiwgImZpcmVicmljazQiKSwKICBzY2FsZV92YWx1ZXMgPSBjKC0wLjUsLTAuMjUsIDAsIDIuNSwgNC41LCA2LjUpLCAjIEFkanVzdCBiYXNlZCBvbiB5b3VyIGRhdGEgcmFuZ2UKICBncm91cF9tZWFucyA9IEZBTFNFLCAjIFNldCB0byBGQUxTRSBpZiB5b3Ugd2FudCBpbmRpdmlkdWFsIHNhbXBsZXMKICBjZWxsX3dpZHRoID0gMjAsICMgQ29udHJvbCBjb2x1bW4gd2lkdGgKICBjZWxsX2hlaWdodCA9IDEwICMgQ29udHJvbCByb3cgaGVpZ2h0CikKCgojIGxpc3QgaXMgdG9vIGxvbmcKYGBgCgoKCmBgYHtyfQpseXNvbWUgPC0gcmVhZF9leGNlbCgiL1VzZXJzL3JoYWxlbmF0aG9tYXMvRG93bmxvYWRzL01vdmVfRGF0YS9EYXJrR2Vub21lUmVzdWx0L0xpc3Qgb2YgZ2VuZXMgZm9yIFJOQXNlcSBvciBQcm90ZW9taWNzL0xZU09TT01FX0dFTkUgTElTVC54bHN4IikKYGBgCgpgYGB7cn0KCmBgYAoKCgpHZW5lIGxpc3QgCgpgYGB7cixmaWcuaGVpZ2h0PTZ9CgoKZGYubG9uZyA8LSBwcm90ZWluX3pzY29yZShkYXRhID0gZGYsCiAgcHJvdGVpbnMgPSBseXNvbWUkYEdlbmUgbmFtZWAsICMgRXhhbXBsZSBwcm90ZWluIG5hbWVzCiAgc2FtcGxlX3BhdHRlcm5zID0gYygiQ29udHJvbCIsIklOUFA1Ri5LTyIsIklHU0Y5Qi5LTyIgLCJTSDNHTDIuS08iLCJJUDZLMi5LTyIpLCBncm91cF9tZWFucyA9IFRSVUUpIAogIAptYXgoZGYubG9uZyRBYnVuZGFuY2UpCm1pbihkZi5sb25nJEFidW5kYW5jZSkKCgojIEV4YW1wbGUgdXNhZ2UKaGVhdG1hcF9wbG90IDwtIHBsb3RfY2x1c3RlcmVkX3Byb3RlaW5faGVhdG1hcF96c2NvcmUoCiAgZGF0YSA9IGRmLAogIHByb3RlaW5zID0gbHlzb21lJGBHZW5lIG5hbWVgLCAjIEV4YW1wbGUgcHJvdGVpbiBuYW1lcwogIHNhbXBsZV9wYXR0ZXJucyA9IGMoIkNvbnRyb2wiLCAiSU5QUDVGLktPIiwiSUdTRjlCLktPIiwgIlNIM0dMMi5LTyIsIklQNksyLktPIiksCiAgY29sb3JzID0gYygic25vdyIsICJsaWdodGdvbGRlbnJvZDEiLCAiZ29sZDEiLCAiZGFya29yYW5nZTEiLCAicmVkMiIsICJmaXJlYnJpY2s0IiksCiAgc2NhbGVfdmFsdWVzID0gYygtMSwtMC41LCAwLCAyLjUsNSksICMgQWRqdXN0IGJhc2VkIG9uIHlvdXIgZGF0YSByYW5nZQogIGdyb3VwX21lYW5zID0gVFJVRSwgIyBTZXQgdG8gRkFMU0UgaWYgeW91IHdhbnQgaW5kaXZpZHVhbCBzYW1wbGVzCiAgY2VsbF93aWR0aCA9IDIwLCAjIENvbnRyb2wgY29sdW1uIHdpZHRoCiAgY2VsbF9oZWlnaHQgPSAxMCAjIENvbnRyb2wgcm93IGhlaWdodAopCgojIEV4YW1wbGUgdXNhZ2UKaGVhdG1hcF9wbG90IDwtIHBsb3RfY2x1c3RlcmVkX3Byb3RlaW5faGVhdG1hcF96c2NvcmUoCiAgZGF0YSA9IGRmLAogIHByb3RlaW5zID0gbHlzb21lJGBHZW5lIG5hbWVgLCAgIyBFeGFtcGxlIHByb3RlaW4gbmFtZXMKICBzYW1wbGVfcGF0dGVybnMgPSBjKCJDb250cm9sIiwgIklHU0Y5Qi5LTyIsICJTSDNHTDIuS08iLCJJUDZLMi5LTyIpLAogIGNvbG9ycyA9IGMoInNub3ciLCAibGlnaHRnb2xkZW5yb2QxIiwgImdvbGQxIiwgImRhcmtvcmFuZ2UxIiwgInJlZDIiLCAiZmlyZWJyaWNrNCIpLAogIHNjYWxlX3ZhbHVlcyA9IGMoLTEsLTAuNSwgMCwgMi41LDUpLCAjIEFkanVzdCBiYXNlZCBvbiB5b3VyIGRhdGEgcmFuZ2UKICBncm91cF9tZWFucyA9IEZBTFNFLCAjIFNldCB0byBGQUxTRSBpZiB5b3Ugd2FudCBpbmRpdmlkdWFsIHNhbXBsZXMKICBjZWxsX3dpZHRoID0gMjAsICMgQ29udHJvbCBjb2x1bW4gd2lkdGgKICBjZWxsX2hlaWdodCA9IDEwICMgQ29udHJvbCByb3cgaGVpZ2h0CikKCgoKCnBsb3RfcHJvdGVpbl9oZWF0bWFwX3pzY29yZSgKICBkYXRhID0gZGYsCiAgcHJvdGVpbnMgPSBseXNvbWUkYEdlbmUgbmFtZWAsICMgRXhhbXBsZSBwcm90ZWluIG5hbWVzCiAgc2FtcGxlX3BhdHRlcm5zID0gYygiQ29udHJvbCIsIklHU0Y5Qi5LTyIsIklOUFA1Ri5LTyIsIlNIM0dMMi5LTyIsIklQNksyLktPIiksCiAgY29sb3JzID0gYygic25vdyIsICJsaWdodGdvbGRlbnJvZDEiLCAiZ29sZDEiLCAiZGFya29yYW5nZTEiLCJyZWQiLCAicmVkMiIsICJmaXJlYnJpY2s0IiksCiAgc2NhbGVfdmFsdWVzID0gYygtMSwgLTAuNSwtMC4yNSwgMCwgMSwgMi41LCA1LjUpLCAjIEFkanVzdCBiYXNlZCBvbiB5b3VyIGRhdGEgcmFuZ2UKICBncm91cF9tZWFucyA9IFRSVUUsIyBTZXQgdG8gRkFMU0UgaWYgeW91IHdhbnQgaW5kaXZpZHVhbCBzYW1wbGVzCiAgIHRpbGVfd2lkdGggPSAwLjI1CikgCgoKCgpwbG90X3Byb3RlaW5faGVhdG1hcF96c2NvcmUoCiAgZGF0YSA9IGRmLAogIHByb3RlaW5zID0gbHlzb21lJGBHZW5lIG5hbWVgLCAjIEV4YW1wbGUgcHJvdGVpbiBuYW1lcwogIHNhbXBsZV9wYXR0ZXJucyA9IGMoIkNvbnRyb2wiLCJJTlBQNUYuS08iLCJTSDNHTDIuS08iKSwKICBjb2xvcnMgPSBjKCJzbm93IiwgImxpZ2h0Z29sZGVucm9kMSIsICJnb2xkMSIsICJkYXJrb3JhbmdlMSIsInJlZCIsICJyZWQyIiwgImZpcmVicmljazQiKSwKICBzY2FsZV92YWx1ZXMgPSBjKC0xLCAtMC41LC0wLjI1LCAwLCAxLCAyLjUsIDUuNSksICMgQWRqdXN0IGJhc2VkIG9uIHlvdXIgZGF0YSByYW5nZQogIGdyb3VwX21lYW5zID0gVFJVRSwjIFNldCB0byBGQUxTRSBpZiB5b3Ugd2FudCBpbmRpdmlkdWFsIHNhbXBsZXMKICAgdGlsZV93aWR0aCA9IDAuMjUKKSAKCgoKCgpgYGAKCmdldCBvdmVybGFwIGxpc3RzCgpgYGB7cn0KY29sbmFtZXMoZGYpCmBgYAoKCgoKYGBge3J9CmNvbnRyYXN0X2xpc3QgPC0gYygiSU5QUDVGLUtPIiwiU0gzR0wyLUtPIikgIyBTcGVjaWZ5IHRoZSBjb250cmFzdHMgb2YgaW50ZXJlc3QKCnJlc3VsdC5seXNvIDwtIGdldF9nZW5lX292ZXJsYXBfYW5kX3VuaXF1ZShmaWx0ZXJlZF9ERVAsIGNvbnRyYXN0X2xpc3QpCgpwcmludChyZXN1bHQubHlzbyRgT3ZlcmxhcHBpbmcgR2VuZXNgKQoKI3dyaXRlLmNzdihyZXN1bHQubHlzbyRgT3ZlcmxhcHBpbmcgR2VuZXNgKQoKCmNvbnRyYXN0X2xpc3QgPC0gYygiU05DQS1BNTNUIiwiUElOSzEtS08iLCJQUktOLUtPIikgIyBTcGVjaWZ5IHRoZSBjb250cmFzdHMgb2YgaW50ZXJlc3QKYTUzLnBpbmsucGFya2luIDwtIGdldF9nZW5lX292ZXJsYXBfYW5kX3VuaXF1ZShmaWx0ZXJlZF9ERVAsIGNvbnRyYXN0X2xpc3QpCgoKCgpjb250cmFzdF9saXN0IDwtIGMoIklOUFA1Ri1LTyIsIlNIM0dMMi1LTyIsIklQNksyLUtPIiwiSUdTRjlCLUtPIikgIyBTcGVjaWZ5IHRoZSBjb250cmFzdHMgb2YgaW50ZXJlc3QKZGFyay5vbCA8LSBnZXRfZ2VuZV9vdmVybGFwX2FuZF91bmlxdWUoZmlsdGVyZWRfREVQLCBjb250cmFzdF9saXN0KQoKcHJpbnQoZGFyay5vbCkKCnByaW50KGE1My5waW5rLnBhcmtpbikKCmZpbHRlcmVkX0RFUCRgR0JBLUtPYAoKCmRmLmdiYSA8LSBmaWx0ZXJlZF9ERVAkYEdCQS1LT2AKCmRmLmlucHAgPC0gCgpgYGAKCnNwZWNpZnkgZ3JvdXAgZnVuY3Rpb24gdG8gZ2V0IHRoZSBzcGVjaWZpYyBvdmVybGFwIGxpc3QgaW4gdGhlIHVwc2V0IHBsb3QKCgpgYGB7cn0KCiMgdGhpcyBjb2RlIHNob3VsZCBnZXQgdGhlIGdlbmVzIG92ZXJsYXBwaW5nIGluIHRoZSBjb250cmFzdCBsaXN0IGFuZCBOT1QgZm91bmQgaW4gdGhlIG90aGVyIGNvbnRyYXN0cwoKIyBGdW5jdGlvbiB0byBleHRyYWN0IGdlbmVzIG92ZXJsYXBwaW5nIGluIGNvbnRyYXN0X2xpc3QgYnV0IG5vdCBpbiBvdGhlciBjb250cmFzdHMKZ2V0X3NwZWNpZmljX2dlbmVfb3ZlcmxhcCA8LSBmdW5jdGlvbihmaWx0ZXJlZF9ERVAsIGNvbnRyYXN0X2xpc3QpIHsKICAKICAjIENoZWNrIGlmIGFsbCBjb250cmFzdHMgaW4gY29udHJhc3RfbGlzdCBleGlzdCBpbiBmaWx0ZXJlZF9ERVAKICBtaXNzaW5nX2NvbnRyYXN0cyA8LSBzZXRkaWZmKGNvbnRyYXN0X2xpc3QsIG5hbWVzKGZpbHRlcmVkX0RFUCkpCiAgaWYgKGxlbmd0aChtaXNzaW5nX2NvbnRyYXN0cykgPiAwKSB7CiAgICBzdG9wKHBhc3RlKCJUaGUgZm9sbG93aW5nIGNvbnRyYXN0cyBhcmUgbm90IGZvdW5kIGluIGZpbHRlcmVkX0RFUDoiLCBwYXN0ZShtaXNzaW5nX2NvbnRyYXN0cywgY29sbGFwc2UgPSAiLCAiKSkpCiAgfQoKICAjIEV4dHJhY3QgZ2VuZSBsaXN0cyBmb3IgY29udHJhc3RzIGluIHRoZSBjb250cmFzdF9saXN0CiAgZ2VuZV9saXN0c19pbmNsdWRlZCA8LSBsYXBwbHkoY29udHJhc3RfbGlzdCwgZnVuY3Rpb24oY29udHJhc3QpIHVuaXF1ZShmaWx0ZXJlZF9ERVBbW2NvbnRyYXN0XV0kU3ltYm9sKSkKICBuYW1lcyhnZW5lX2xpc3RzX2luY2x1ZGVkKSA8LSBjb250cmFzdF9saXN0CgogICMgRXh0cmFjdCBnZW5lIGxpc3RzIGZvciBjb250cmFzdHMgbm90IGluIHRoZSBjb250cmFzdF9saXN0CiAgb3RoZXJfY29udHJhc3RzIDwtIHNldGRpZmYobmFtZXMoZmlsdGVyZWRfREVQKSwgY29udHJhc3RfbGlzdCkKICBnZW5lX2xpc3RzX2V4Y2x1ZGVkIDwtIGxhcHBseShvdGhlcl9jb250cmFzdHMsIGZ1bmN0aW9uKGNvbnRyYXN0KSB1bmlxdWUoZmlsdGVyZWRfREVQW1tjb250cmFzdF1dJFN5bWJvbCkpCgogICMgRmluZCBvdmVybGFwcGluZyBnZW5lcyBhbW9uZyB0aGUgc3BlY2lmaWVkIGNvbnRyYXN0cyBpbiBjb250cmFzdF9saXN0CiAgb3ZlcmxhcHBpbmdfZ2VuZXNfaW5jbHVkZWQgPC0gUmVkdWNlKGludGVyc2VjdCwgZ2VuZV9saXN0c19pbmNsdWRlZCkKICAKICAjIEZpbmQgZ2VuZXMgdGhhdCBhcmUgaW4gdGhlIGV4Y2x1ZGVkIGNvbnRyYXN0cwogIGdlbmVzX2luX2V4Y2x1ZGVkIDwtIHVuaXF1ZSh1bmxpc3QoZ2VuZV9saXN0c19leGNsdWRlZCkpCiAgCiAgIyBFeGNsdWRlIGdlbmVzIHRoYXQgYXJlIGluIHRoZSBleGNsdWRlZCBjb250cmFzdHMgZnJvbSB0aGUgb3ZlcmxhcHBpbmcgZ2VuZXMKICBmaW5hbF9nZW5lcyA8LSBzZXRkaWZmKG92ZXJsYXBwaW5nX2dlbmVzX2luY2x1ZGVkLCBnZW5lc19pbl9leGNsdWRlZCkKICAKICByZXR1cm4oZmluYWxfZ2VuZXMpCn0KCiMgRXhhbXBsZSB1c2FnZQpjb250cmFzdF9saXN0IDwtIGMoIlNOQ0EtQTUzVCIsICJHQkEtS08iLCAiUElOSzEtS08iLCAiUFJLTi1LTyIpCm92ZXJsYXBfZ2VuZXMgPC0gZ2V0X3NwZWNpZmljX2dlbmVfb3ZlcmxhcChmaWx0ZXJlZF9ERVAsIGNvbnRyYXN0X2xpc3QpCgojIFByaW50IHRoZSByZXN1bHQKcHJpbnQob3ZlcmxhcF9nZW5lcykKCmxlbmd0aChvdmVybGFwX2dlbmVzKSAjIDQwIGlzIHRoZSBzYW1lIGxlbmdodCBhcyB0aGUgdXBzZXQgcGxvdAoKIyBFeGFtcGxlIHVzYWdlCmNvbnRyYXN0X2xpc3QgPC0gYygiR0JBLUtPIiwgIlBJTksxLUtPIiwgIlBSS04tS08iKQpvdmVybGFwX2dlbmVzIDwtIGdldF9zcGVjaWZpY19nZW5lX292ZXJsYXAoZmlsdGVyZWRfREVQLCBjb250cmFzdF9saXN0KQoKIyBQcmludCB0aGUgcmVzdWx0CnByaW50KG92ZXJsYXBfZ2VuZXMpCgpsZW5ndGgob3ZlcmxhcF9nZW5lcykKCndyaXRlLmNzdihvdmVybGFwX2dlbmVzLCIvVXNlcnMvcmhhbGVuYXRob21hcy9Eb3dubG9hZHMvTW92ZV9EYXRhL0RhcmtHZW5vbWVSZXN1bHQvb21pY3MvT3ZlcmxhcExHZW5lTGlzdHMvR0JBX1BJTksxX1BSS05fRFBFLmNzdiIpCgoKYGBgCgpNYWtlIGxpc3QgY29ycmVzcG9uZGluZyB0byB0aGUgdXBzZXQgcGxvdCB0byBzYXZlIGFuZCBzZW5kIHRvIFJveGFubmUgCgoKYGBge3J9CgojIHBpbmsgcGFya2luCmNvbnRyYXN0X2xpc3QgPC0gYygiUElOSzEtS08iLCAiUFJLTi1LTyIpCm92ZXJsYXBfZ2VuZXMgPC0gZ2V0X3NwZWNpZmljX2dlbmVfb3ZlcmxhcChmaWx0ZXJlZF9ERVAsIGNvbnRyYXN0X2xpc3QpCiMgUHJpbnQgdGhlIHJlc3VsdApwcmludCgiT3ZlcmxhcCBvZiBQSU5LMSBQUktOIikKcHJpbnQob3ZlcmxhcF9nZW5lcykKbGVuZ3RoKG92ZXJsYXBfZ2VuZXMpCndyaXRlLmNzdihvdmVybGFwX2dlbmVzLCIvVXNlcnMvcmhhbGVuYXRob21hcy9Eb3dubG9hZHMvTW92ZV9EYXRhL0RhcmtHZW5vbWVSZXN1bHQvb21pY3MvT3ZlcmxhcExHZW5lTGlzdHMvUElOSzFfUFJLTl9EUEUuY3N2IikKcHJpbnQoInNhdmVkIikKCiMgUFJLTiBJR1NGOUIKY29udHJhc3RfbGlzdCA8LSBjKCJJR1NGOUItS08iLCAiUFJLTi1LTyIpCm92ZXJsYXBfZ2VuZXMgPC0gZ2V0X3NwZWNpZmljX2dlbmVfb3ZlcmxhcChmaWx0ZXJlZF9ERVAsIGNvbnRyYXN0X2xpc3QpCiMgUHJpbnQgdGhlIHJlc3VsdApwcmludCgiT3ZlcmxhcCBvZiBJR1NGOUIgUFJLTiIpCnByaW50KG92ZXJsYXBfZ2VuZXMpCmxlbmd0aChvdmVybGFwX2dlbmVzKQp3cml0ZS5jc3Yob3ZlcmxhcF9nZW5lcywiL1VzZXJzL3JoYWxlbmF0aG9tYXMvRG93bmxvYWRzL01vdmVfRGF0YS9EYXJrR2Vub21lUmVzdWx0L29taWNzL092ZXJsYXBMR2VuZUxpc3RzL0lHU0Y5Ql9QUktOX0RQRS5jc3YiKQpwcmludCgic2F2ZWQiKQoKIyBJR1NGOUIgcGluayBwYXJraW4KY29udHJhc3RfbGlzdCA8LSBjKCJQSU5LMS1LTyIsICJQUktOLUtPIiwgIklHU0Y5Qi1LTyIpCm92ZXJsYXBfZ2VuZXMgPC0gZ2V0X3NwZWNpZmljX2dlbmVfb3ZlcmxhcChmaWx0ZXJlZF9ERVAsIGNvbnRyYXN0X2xpc3QpCiMgUHJpbnQgdGhlIHJlc3VsdApwcmludCgiT3ZlcmxhcCBvZiBJR1NGOUIgUElOSzEgUFJLTiIpCnByaW50KG92ZXJsYXBfZ2VuZXMpCmxlbmd0aChvdmVybGFwX2dlbmVzKQp3cml0ZS5jc3Yob3ZlcmxhcF9nZW5lcywiL1VzZXJzL3JoYWxlbmF0aG9tYXMvRG93bmxvYWRzL01vdmVfRGF0YS9EYXJrR2Vub21lUmVzdWx0L29taWNzL092ZXJsYXBMR2VuZUxpc3RzL0lHU0Y5Ql9QSU5LMV9QUktOX0RQRS5jc3YiKQpwcmludCgic2F2ZWQiKQoKIyBQUktOIElHU0Y5Qgpjb250cmFzdF9saXN0IDwtIGMoIklHU0Y5Qi1LTyIsICJQSU5LMS1LTyIpCm92ZXJsYXBfZ2VuZXMgPC0gZ2V0X3NwZWNpZmljX2dlbmVfb3ZlcmxhcChmaWx0ZXJlZF9ERVAsIGNvbnRyYXN0X2xpc3QpCiMgUHJpbnQgdGhlIHJlc3VsdApwcmludCgiT3ZlcmxhcCBvZiBJR1NGOUIgUElOSzEiKQpwcmludChvdmVybGFwX2dlbmVzKQpsZW5ndGgob3ZlcmxhcF9nZW5lcykKd3JpdGUuY3N2KG92ZXJsYXBfZ2VuZXMsIi9Vc2Vycy9yaGFsZW5hdGhvbWFzL0Rvd25sb2Fkcy9Nb3ZlX0RhdGEvRGFya0dlbm9tZVJlc3VsdC9vbWljcy9PdmVybGFwTEdlbmVMaXN0cy9JR1NGOUJfUElOSzFfRFBFLmNzdiIpCnByaW50KCJzYXZlZCIpCgoKIyBJTlBQNUYgSUdTRjlCCmNvbnRyYXN0X2xpc3QgPC0gYygiSUdTRjlCLUtPIiwgIklOUFA1Ri1LTyIpCm92ZXJsYXBfZ2VuZXMgPC0gZ2V0X3NwZWNpZmljX2dlbmVfb3ZlcmxhcChmaWx0ZXJlZF9ERVAsIGNvbnRyYXN0X2xpc3QpCiMgUHJpbnQgdGhlIHJlc3VsdApwcmludCgiT3ZlcmxhcCBvZiBJR1NGOUIgSU5QUDVGIikKcHJpbnQob3ZlcmxhcF9nZW5lcykKbGVuZ3RoKG92ZXJsYXBfZ2VuZXMpCndyaXRlLmNzdihvdmVybGFwX2dlbmVzLCIvVXNlcnMvcmhhbGVuYXRob21hcy9Eb3dubG9hZHMvTW92ZV9EYXRhL0RhcmtHZW5vbWVSZXN1bHQvb21pY3MvT3ZlcmxhcExHZW5lTGlzdHMvSUdTRjlCX0lOUFA1Rl9EUEUuY3N2IikKcHJpbnQoInNhdmVkIikKCgojIElOUFA1RiBTSDNHTDIKY29udHJhc3RfbGlzdCA8LSBjKCJTSDNHTDItS08iLCAiSU5QUDVGLUtPIikKb3ZlcmxhcF9nZW5lcyA8LSBnZXRfc3BlY2lmaWNfZ2VuZV9vdmVybGFwKGZpbHRlcmVkX0RFUCwgY29udHJhc3RfbGlzdCkKIyBQcmludCB0aGUgcmVzdWx0CnByaW50KCJPdmVybGFwIG9mIFNIM0dMMiBJTlBQNUYiKQpwcmludChvdmVybGFwX2dlbmVzKQpsZW5ndGgob3ZlcmxhcF9nZW5lcykKd3JpdGUuY3N2KG92ZXJsYXBfZ2VuZXMsIi9Vc2Vycy9yaGFsZW5hdGhvbWFzL0Rvd25sb2Fkcy9Nb3ZlX0RhdGEvRGFya0dlbm9tZVJlc3VsdC9vbWljcy9PdmVybGFwTEdlbmVMaXN0cy9TSDNHTDJfSU5QUDVGX0RQRS5jc3YiKQpwcmludCgic2F2ZWQiKQoKCiMgU05DQSBBNTNUIHBpbmsgcGFya2luCmNvbnRyYXN0X2xpc3QgPC0gYygiUElOSzEtS08iLCAiUFJLTi1LTyIsICJTTkNBLUE1M1QiKQpvdmVybGFwX2dlbmVzIDwtIGdldF9zcGVjaWZpY19nZW5lX292ZXJsYXAoZmlsdGVyZWRfREVQLCBjb250cmFzdF9saXN0KQojIFByaW50IHRoZSByZXN1bHQKcHJpbnQoIk92ZXJsYXAgb2YgU05DQSBBNTNUIFBJTksxIFBSS04iKQpwcmludChvdmVybGFwX2dlbmVzKQpsZW5ndGgob3ZlcmxhcF9nZW5lcykKd3JpdGUuY3N2KG92ZXJsYXBfZ2VuZXMsIi9Vc2Vycy9yaGFsZW5hdGhvbWFzL0Rvd25sb2Fkcy9Nb3ZlX0RhdGEvRGFya0dlbm9tZVJlc3VsdC9vbWljcy9PdmVybGFwTEdlbmVMaXN0cy9TTkNBQTUzVF9QSU5LMV9QUktOX0RQRS5jc3YiKQpwcmludCgic2F2ZWQiKQoKIyBicmlnaHQgZ2Vub21lIGFuZCBJR1NGOUIKY29udHJhc3RfbGlzdCA8LSBjKCJTTkNBLUE1M1QiLCAiR0JBLUtPIiwgIlBJTksxLUtPIiwgIlBSS04tS08iLCAiSUdTRjlCLUtPIikKb3ZlcmxhcF9nZW5lcyA8LSBnZXRfc3BlY2lmaWNfZ2VuZV9vdmVybGFwKGZpbHRlcmVkX0RFUCwgY29udHJhc3RfbGlzdCkKIyBQcmludCB0aGUgcmVzdWx0CnByaW50KCJPdmVybGFwIG9mIFNOQ0EgR0JBIFBJTksxIFBSS04gSUdTRjlCIikKcHJpbnQob3ZlcmxhcF9nZW5lcykKbGVuZ3RoKG92ZXJsYXBfZ2VuZXMpCndyaXRlLmNzdihvdmVybGFwX2dlbmVzLCIvVXNlcnMvcmhhbGVuYXRob21hcy9Eb3dubG9hZHMvTW92ZV9EYXRhL0RhcmtHZW5vbWVSZXN1bHQvb21pY3MvT3ZlcmxhcExHZW5lTGlzdHMvU05DQUE1M1RfR0JBX1BJTksxX1BSS05fSUdTRjlCX0RQRS5jc3YiKQpwcmludCgic2F2ZWQiKQoKCgojIGJyaWdodCBnZW5vbWUKY29udHJhc3RfbGlzdCA8LSBjKCJTTkNBLUE1M1QiLCAiR0JBLUtPIiwgIlBJTksxLUtPIiwgIlBSS04tS08iKQpvdmVybGFwX2dlbmVzIDwtIGdldF9zcGVjaWZpY19nZW5lX292ZXJsYXAoZmlsdGVyZWRfREVQLCBjb250cmFzdF9saXN0KQojIFByaW50IHRoZSByZXN1bHQKcHJpbnQoIk92ZXJsYXAgb2YgU05DQSBHQkEgUElOSzEgUFJLTiIpCnByaW50KG92ZXJsYXBfZ2VuZXMpCmxlbmd0aChvdmVybGFwX2dlbmVzKQp3cml0ZS5jc3Yob3ZlcmxhcF9nZW5lcywiL1VzZXJzL3JoYWxlbmF0aG9tYXMvRG93bmxvYWRzL01vdmVfRGF0YS9EYXJrR2Vub21lUmVzdWx0L29taWNzL092ZXJsYXBMR2VuZUxpc3RzL1NOQ0FBNTNUX0dCQV9QSU5LMV9QUktOX0RQRS5jc3YiKQpwcmludCgic2F2ZWQiKQoKCmBgYAoKYGBge3J9CgoKY29udHJhc3RfbGlzdCA8LSBjKCJTSDNHTDItS08iLCAiSU5QUDVGLUtPIiwiSUdTRjlCLUtPIikKb3ZlcmxhcF9nZW5lcyA8LSBnZXRfc3BlY2lmaWNfZ2VuZV9vdmVybGFwKGZpbHRlcmVkX0RFUCwgY29udHJhc3RfbGlzdCkKIyBQcmludCB0aGUgcmVzdWx0CnByaW50KCJPdmVybGFwIG9mIFNIM0dMMiBJTlBQNUYgSUdTRjlCIikKcHJpbnQob3ZlcmxhcF9nZW5lcykKbGVuZ3RoKG92ZXJsYXBfZ2VuZXMpCndyaXRlLmNzdihvdmVybGFwX2dlbmVzLCIvVXNlcnMvcmhhbGVuYXRob21hcy9Eb3dubG9hZHMvTW92ZV9EYXRhL0RhcmtHZW5vbWVSZXN1bHQvb21pY3MvT3ZlcmxhcExHZW5lTGlzdHMvSUdTRjlCX0lOUFA1Rl9TSDNHTDJfRFBFLmNzdiIpCnByaW50KCJzYXZlZCIpCgoKIyBJR1NGOUIgcGluayBwYXJraW4gU05DQQpjb250cmFzdF9saXN0IDwtIGMoIlBJTksxLUtPIiwgIlBSS04tS08iLCAiSUdTRjlCLUtPIiwiU05DQS1BNTNUIikKb3ZlcmxhcF9nZW5lcyA8LSBnZXRfc3BlY2lmaWNfZ2VuZV9vdmVybGFwKGZpbHRlcmVkX0RFUCwgY29udHJhc3RfbGlzdCkKIyBQcmludCB0aGUgcmVzdWx0CnByaW50KCJPdmVybGFwIG9mIElHU0Y5QiBQSU5LMSBQUktOIFNOQ0EtQTUzVCIpCnByaW50KG92ZXJsYXBfZ2VuZXMpCmxlbmd0aChvdmVybGFwX2dlbmVzKQp3cml0ZS5jc3Yob3ZlcmxhcF9nZW5lcywiL1VzZXJzL3JoYWxlbmF0aG9tYXMvRG93bmxvYWRzL01vdmVfRGF0YS9EYXJrR2Vub21lUmVzdWx0L29taWNzL092ZXJsYXBMR2VuZUxpc3RzL1NOQ0FBNTNUX0lHU0Y5Ql9QSU5LMV9QUktOX0RQRS5jc3YiKQpwcmludCgic2F2ZWQiKQoKCmNvbnRyYXN0X2xpc3QgPC0gYygiUElOSzEtS08iLCAiUFJLTi1LTyIsICJJR1NGOUItS08iLCJHQkEtS08iKQpvdmVybGFwX2dlbmVzIDwtIGdldF9zcGVjaWZpY19nZW5lX292ZXJsYXAoZmlsdGVyZWRfREVQLCBjb250cmFzdF9saXN0KQojIFByaW50IHRoZSByZXN1bHQKcHJpbnQoIk92ZXJsYXAgb2YgSUdTRjlCIFBJTksxIFBSS04gR0JBIikKcHJpbnQob3ZlcmxhcF9nZW5lcykKbGVuZ3RoKG92ZXJsYXBfZ2VuZXMpCndyaXRlLmNzdihvdmVybGFwX2dlbmVzLCIvVXNlcnMvcmhhbGVuYXRob21hcy9Eb3dubG9hZHMvTW92ZV9EYXRhL0RhcmtHZW5vbWVSZXN1bHQvb21pY3MvT3ZlcmxhcExHZW5lTGlzdHMvR0JBX0lHU0Y5Ql9QSU5LMV9QUktOX0RQRS5jc3YiKQpwcmludCgic2F2ZWQiKQoKCgoKYGBgCgpgYGB7cn0KCgojIEE1M1QgSUdTRjlCCmNvbnRyYXN0X2xpc3QgPC0gYygiSUdTRjlCLUtPIiwgIlNOQ0EtQTUzVCIpCm92ZXJsYXBfZ2VuZXMgPC0gZ2V0X3NwZWNpZmljX2dlbmVfb3ZlcmxhcChmaWx0ZXJlZF9ERVAsIGNvbnRyYXN0X2xpc3QpCiMgUHJpbnQgdGhlIHJlc3VsdApwcmludCgiT3ZlcmxhcCBvZiBJR1NGOUIgU05DQSBBNTNUIikKcHJpbnQob3ZlcmxhcF9nZW5lcykKbGVuZ3RoKG92ZXJsYXBfZ2VuZXMpCndyaXRlLmNzdihvdmVybGFwX2dlbmVzLCIvVXNlcnMvcmhhbGVuYXRob21hcy9Eb3dubG9hZHMvTW92ZV9EYXRhL0RhcmtHZW5vbWVSZXN1bHQvb21pY3MvT3ZlcmxhcExHZW5lTGlzdHMvSUdTRjlCX1NOQ0FBNTNUX0RQRS5jc3YiKQpwcmludCgic2F2ZWQiKQoKIyBBNTNUIElHU0Y5Qgpjb250cmFzdF9saXN0IDwtIGMoIklHU0Y5Qi1LTyIsICJTSDNHTDItS08iKQpvdmVybGFwX2dlbmVzIDwtIGdldF9zcGVjaWZpY19nZW5lX292ZXJsYXAoZmlsdGVyZWRfREVQLCBjb250cmFzdF9saXN0KQojIFByaW50IHRoZSByZXN1bHQKcHJpbnQoIk92ZXJsYXAgb2YgSUdTRjlCIFNIM0dMMiIpCnByaW50KG92ZXJsYXBfZ2VuZXMpCmxlbmd0aChvdmVybGFwX2dlbmVzKQp3cml0ZS5jc3Yob3ZlcmxhcF9nZW5lcywiL1VzZXJzL3JoYWxlbmF0aG9tYXMvRG93bmxvYWRzL01vdmVfRGF0YS9EYXJrR2Vub21lUmVzdWx0L29taWNzL092ZXJsYXBMR2VuZUxpc3RzL0lHU0Y5Ql9TSDNHTDJfRFBFLmNzdiIpCnByaW50KCJzYXZlZCIpCgojIEE1M1QgSUdTRjlCCmNvbnRyYXN0X2xpc3QgPC0gYygiSUdTRjlCLUtPIiwgIklQNksyLUtPIikKb3ZlcmxhcF9nZW5lcyA8LSBnZXRfc3BlY2lmaWNfZ2VuZV9vdmVybGFwKGZpbHRlcmVkX0RFUCwgY29udHJhc3RfbGlzdCkKIyBQcmludCB0aGUgcmVzdWx0CnByaW50KCJPdmVybGFwIG9mIElHU0Y5QiBJUDZLIikKcHJpbnQob3ZlcmxhcF9nZW5lcykKbGVuZ3RoKG92ZXJsYXBfZ2VuZXMpCndyaXRlLmNzdihvdmVybGFwX2dlbmVzLCIvVXNlcnMvcmhhbGVuYXRob21hcy9Eb3dubG9hZHMvTW92ZV9EYXRhL0RhcmtHZW5vbWVSZXN1bHQvb21pY3MvT3ZlcmxhcExHZW5lTGlzdHMvSUdTRjlCX0lQNksyX0RQRS5jc3YiKQpwcmludCgic2F2ZWQiKQoKCiMgQTUzVCBQSU5LMQpjb250cmFzdF9saXN0IDwtIGMoIlBJTksxLUtPIiwgIlNOQ0EtQTUzVCIpCm92ZXJsYXBfZ2VuZXMgPC0gZ2V0X3NwZWNpZmljX2dlbmVfb3ZlcmxhcChmaWx0ZXJlZF9ERVAsIGNvbnRyYXN0X2xpc3QpCiMgUHJpbnQgdGhlIHJlc3VsdApwcmludCgiT3ZlcmxhcCBvZiBQSU5LMUtPIFNOQ0EgQTUzVCIpCnByaW50KG92ZXJsYXBfZ2VuZXMpCmxlbmd0aChvdmVybGFwX2dlbmVzKQp3cml0ZS5jc3Yob3ZlcmxhcF9nZW5lcywiL1VzZXJzL3JoYWxlbmF0aG9tYXMvRG93bmxvYWRzL01vdmVfRGF0YS9EYXJrR2Vub21lUmVzdWx0L29taWNzL092ZXJsYXBMR2VuZUxpc3RzL1BJTksxX1NOQ0FBNTNUX0RQRS5jc3YiKQpwcmludCgic2F2ZWQiKQoKCiMgQTUzVCBQSU5LMSBHQkEKY29udHJhc3RfbGlzdCA8LSBjKCJQSU5LMS1LTyIsICJTTkNBLUE1M1QiLCJHQkEtS08iKQpvdmVybGFwX2dlbmVzIDwtIGdldF9zcGVjaWZpY19nZW5lX292ZXJsYXAoZmlsdGVyZWRfREVQLCBjb250cmFzdF9saXN0KQojIFByaW50IHRoZSByZXN1bHQKcHJpbnQoIk92ZXJsYXAgb2YgUElOSzFLTyBTTkNBIEE1M1QgYW5kIEdCQSIpCnByaW50KG92ZXJsYXBfZ2VuZXMpCmxlbmd0aChvdmVybGFwX2dlbmVzKQp3cml0ZS5jc3Yob3ZlcmxhcF9nZW5lcywiL1VzZXJzL3JoYWxlbmF0aG9tYXMvRG93bmxvYWRzL01vdmVfRGF0YS9EYXJrR2Vub21lUmVzdWx0L29taWNzL092ZXJsYXBMR2VuZUxpc3RzL1BJTksxX1NOQ0FBNTNUX0dCQV9EUEUuY3N2IikKcHJpbnQoInNhdmVkIikKCgojIEE1M1QgUElOSzEgSUdTRjlCCmNvbnRyYXN0X2xpc3QgPC0gYygiUElOSzEtS08iLCAiU05DQS1BNTNUIiwiSUdTRjlCLUtPIikKb3ZlcmxhcF9nZW5lcyA8LSBnZXRfc3BlY2lmaWNfZ2VuZV9vdmVybGFwKGZpbHRlcmVkX0RFUCwgY29udHJhc3RfbGlzdCkKIyBQcmludCB0aGUgcmVzdWx0CnByaW50KCJPdmVybGFwIG9mIFBJTksxS08gU05DQSBBNTNUIGFuZCBJR1NGOUIiKQpwcmludChvdmVybGFwX2dlbmVzKQpsZW5ndGgob3ZlcmxhcF9nZW5lcykKd3JpdGUuY3N2KG92ZXJsYXBfZ2VuZXMsIi9Vc2Vycy9yaGFsZW5hdGhvbWFzL0Rvd25sb2Fkcy9Nb3ZlX0RhdGEvRGFya0dlbm9tZVJlc3VsdC9vbWljcy9PdmVybGFwTEdlbmVMaXN0cy9QSU5LMV9TTkNBQTUzVF9JR1NGOUJfRFBFLmNzdiIpCnByaW50KCJzYXZlZCIpCgojIGRhcmsgZ2Vub21lCmNvbnRyYXN0X2xpc3QgPC0gYygiU0gzR0wyLUtPIiwgIklOUFA1Ri1LTyIsIklHU0Y5Qi1LTyIsICJJUDZLMi1LTyIpCm92ZXJsYXBfZ2VuZXMgPC0gZ2V0X3NwZWNpZmljX2dlbmVfb3ZlcmxhcChmaWx0ZXJlZF9ERVAsIGNvbnRyYXN0X2xpc3QpCiMgUHJpbnQgdGhlIHJlc3VsdApwcmludCgiT3ZlcmxhcCBvZiBTSDNHTDIgSU5QUDVGIElHU0Y5QiIpCnByaW50KG92ZXJsYXBfZ2VuZXMpCmxlbmd0aChvdmVybGFwX2dlbmVzKQp3cml0ZS5jc3Yob3ZlcmxhcF9nZW5lcywiL1VzZXJzL3JoYWxlbmF0aG9tYXMvRG93bmxvYWRzL01vdmVfRGF0YS9EYXJrR2Vub21lUmVzdWx0L29taWNzL092ZXJsYXBMR2VuZUxpc3RzL0lHU0Y5Ql9JTlBQNUZfU0gzR0wyX0lQNksyX0RQRS5jc3YiKQpwcmludCgic2F2ZWQiKQoKCgoKYGBgCgpJbmRpdmlkdWFsIGNvbnRyYXN0cwpgYGB7cn0KCmNvbnRyYXN0X2xpc3QgPC0gYygiU05DQS1BNTNUIikKb3ZlcmxhcF9nZW5lcyA8LSBnZXRfc3BlY2lmaWNfZ2VuZV9vdmVybGFwKGZpbHRlcmVkX0RFUCwgY29udHJhc3RfbGlzdCkKIyBQcmludCB0aGUgcmVzdWx0CnByaW50KCJVbmlxdWUgdG8gU05DQSBBNTNUIikKcHJpbnQob3ZlcmxhcF9nZW5lcykKbGVuZ3RoKG92ZXJsYXBfZ2VuZXMpCndyaXRlLmNzdihvdmVybGFwX2dlbmVzLCIvVXNlcnMvcmhhbGVuYXRob21hcy9Eb3dubG9hZHMvTW92ZV9EYXRhL0RhcmtHZW5vbWVSZXN1bHQvb21pY3MvT3ZlcmxhcExHZW5lTGlzdHMvU05DQUE1M1RfRFBFLmNzdiIpCnByaW50KCJzYXZlZCIpCgpjb250cmFzdF9saXN0IDwtIGMoIkdCQS1LTyIpCm92ZXJsYXBfZ2VuZXMgPC0gZ2V0X3NwZWNpZmljX2dlbmVfb3ZlcmxhcChmaWx0ZXJlZF9ERVAsIGNvbnRyYXN0X2xpc3QpCiMgUHJpbnQgdGhlIHJlc3VsdApwcmludCgiVW5pcXVlIHRvIEdCQSBLTyIpCnByaW50KG92ZXJsYXBfZ2VuZXMpCmxlbmd0aChvdmVybGFwX2dlbmVzKQp3cml0ZS5jc3Yob3ZlcmxhcF9nZW5lcywiL1VzZXJzL3JoYWxlbmF0aG9tYXMvRG93bmxvYWRzL01vdmVfRGF0YS9EYXJrR2Vub21lUmVzdWx0L29taWNzL092ZXJsYXBMR2VuZUxpc3RzL0dCQV9EUEUuY3N2IikKcHJpbnQoInNhdmVkIikKCmNvbnRyYXN0X2xpc3QgPC0gYygiUElOSzEtS08iKQpvdmVybGFwX2dlbmVzIDwtIGdldF9zcGVjaWZpY19nZW5lX292ZXJsYXAoZmlsdGVyZWRfREVQLCBjb250cmFzdF9saXN0KQojIFByaW50IHRoZSByZXN1bHQKcHJpbnQoIlVuaXF1ZSB0byBQSU5LMSBLTyIpCnByaW50KG92ZXJsYXBfZ2VuZXMpCmxlbmd0aChvdmVybGFwX2dlbmVzKQp3cml0ZS5jc3Yob3ZlcmxhcF9nZW5lcywiL1VzZXJzL3JoYWxlbmF0aG9tYXMvRG93bmxvYWRzL01vdmVfRGF0YS9EYXJrR2Vub21lUmVzdWx0L29taWNzL092ZXJsYXBMR2VuZUxpc3RzL1BJTksxX0RQRS5jc3YiKQpwcmludCgic2F2ZWQiKQoKCmNvbnRyYXN0X2xpc3QgPC0gYygiUFJLTi1LTyIpCm92ZXJsYXBfZ2VuZXMgPC0gZ2V0X3NwZWNpZmljX2dlbmVfb3ZlcmxhcChmaWx0ZXJlZF9ERVAsIGNvbnRyYXN0X2xpc3QpCiMgUHJpbnQgdGhlIHJlc3VsdApwcmludCgiVW5pcXVlIHRvIFBSS04gS08iKQpwcmludChvdmVybGFwX2dlbmVzKQpsZW5ndGgob3ZlcmxhcF9nZW5lcykKd3JpdGUuY3N2KG92ZXJsYXBfZ2VuZXMsIi9Vc2Vycy9yaGFsZW5hdGhvbWFzL0Rvd25sb2Fkcy9Nb3ZlX0RhdGEvRGFya0dlbm9tZVJlc3VsdC9vbWljcy9PdmVybGFwTEdlbmVMaXN0cy9QUktOX0RQRS5jc3YiKQpwcmludCgic2F2ZWQiKQoKCgpjb250cmFzdF9saXN0IDwtIGMoIklHU0Y5Qi1LTyIpCm92ZXJsYXBfZ2VuZXMgPC0gZ2V0X3NwZWNpZmljX2dlbmVfb3ZlcmxhcChmaWx0ZXJlZF9ERVAsIGNvbnRyYXN0X2xpc3QpCiMgUHJpbnQgdGhlIHJlc3VsdApwcmludCgiVW5pcXVlIHRvIElHU0Y5QiIpCnByaW50KG92ZXJsYXBfZ2VuZXMpCmxlbmd0aChvdmVybGFwX2dlbmVzKQp3cml0ZS5jc3Yob3ZlcmxhcF9nZW5lcywiL1VzZXJzL3JoYWxlbmF0aG9tYXMvRG93bmxvYWRzL01vdmVfRGF0YS9EYXJrR2Vub21lUmVzdWx0L29taWNzL092ZXJsYXBMR2VuZUxpc3RzL0lHU0Y5Ql9EUEUuY3N2IikKcHJpbnQoInNhdmVkIikKCmNvbnRyYXN0X2xpc3QgPC0gYygiSU5QUDVGLUtPIikKb3ZlcmxhcF9nZW5lcyA8LSBnZXRfc3BlY2lmaWNfZ2VuZV9vdmVybGFwKGZpbHRlcmVkX0RFUCwgY29udHJhc3RfbGlzdCkKIyBQcmludCB0aGUgcmVzdWx0CnByaW50KCJVbmlxdWUgdG8gSU5QUDVGIikKcHJpbnQob3ZlcmxhcF9nZW5lcykKbGVuZ3RoKG92ZXJsYXBfZ2VuZXMpCndyaXRlLmNzdihvdmVybGFwX2dlbmVzLCIvVXNlcnMvcmhhbGVuYXRob21hcy9Eb3dubG9hZHMvTW92ZV9EYXRhL0RhcmtHZW5vbWVSZXN1bHQvb21pY3MvT3ZlcmxhcExHZW5lTGlzdHMvSU5QUDVGX0RQRS5jc3YiKQpwcmludCgic2F2ZWQiKQoKY29udHJhc3RfbGlzdCA8LSBjKCJTSDNHTDItS08iKQpvdmVybGFwX2dlbmVzIDwtIGdldF9zcGVjaWZpY19nZW5lX292ZXJsYXAoZmlsdGVyZWRfREVQLCBjb250cmFzdF9saXN0KQojIFByaW50IHRoZSByZXN1bHQKcHJpbnQoIlVuaXF1ZSB0byBTSDNHTDIiKQpwcmludChvdmVybGFwX2dlbmVzKQpsZW5ndGgob3ZlcmxhcF9nZW5lcykKd3JpdGUuY3N2KG92ZXJsYXBfZ2VuZXMsIi9Vc2Vycy9yaGFsZW5hdGhvbWFzL0Rvd25sb2Fkcy9Nb3ZlX0RhdGEvRGFya0dlbm9tZVJlc3VsdC9vbWljcy9PdmVybGFwTEdlbmVMaXN0cy9TSDNHTDJfRFBFLmNzdiIpCnByaW50KCJzYXZlZCIpCgpjb250cmFzdF9saXN0IDwtIGMoIklQNksyLUtPIikKb3ZlcmxhcF9nZW5lcyA8LSBnZXRfc3BlY2lmaWNfZ2VuZV9vdmVybGFwKGZpbHRlcmVkX0RFUCwgY29udHJhc3RfbGlzdCkKIyBQcmludCB0aGUgcmVzdWx0CnByaW50KCJPdmVybGFwIG9mIElQNksyIikKcHJpbnQob3ZlcmxhcF9nZW5lcykKbGVuZ3RoKG92ZXJsYXBfZ2VuZXMpCndyaXRlLmNzdihvdmVybGFwX2dlbmVzLCIvVXNlcnMvcmhhbGVuYXRob21hcy9Eb3dubG9hZHMvTW92ZV9EYXRhL0RhcmtHZW5vbWVSZXN1bHQvb21pY3MvT3ZlcmxhcExHZW5lTGlzdHMvSVA2SzJfRFBFLmNzdiIpCnByaW50KCJzYXZlZCIpCgpgYGAKCgpNYWtlIG9uZSBkYXRhZnJhbWUgZm9yIGV4cHJlc3Npb24gbGlzdHMKCmBgYHtyfQojIGxvb2sgYXQgZWFjaCBhYnVuZGFuY2UgZGF0YWZyYW1lCgpjb2xuYW1lcyhkZi5icmlnaHQpCmNvbG5hbWVzKGRmLmRhcmspCgpkZiA8LSBtZXJnZShkZi5icmlnaHQsIGRmLmRhcmssIGJ5LnggPSAiU3ltYm9sIiwgYnkueSA9ICJTeW1ib2wiKQoKCmBgYAoKClRyeSBzb21lIHBsb3RzCgpgYGB7ciwgZmlnLmhlaWdodD01fQoKCgpkZi5sb25nIDwtIHByb3RlaW5fenNjb3JlKGRhdGEgPSBkZiwKICBwcm90ZWlucyA9IGx5c29tZSRgR2VuZSBuYW1lYCwgIyBFeGFtcGxlIHByb3RlaW4gbmFtZXMKICBzYW1wbGVfcGF0dGVybnMgPSBjKCJDb250cm9sIiwiQTUzVCIsIkdCQS5LTyIsIlBJTksxLktPIiwiUFJLTi5LTyIsIklOUFA1Ri5LTyIsIklHU0Y5Qi5LTyIgLCJTSDNHTDIuS08iLCJJUDZLMi5LTyIpLCBncm91cF9tZWFucyA9IFRSVUUpIAogIAptYXgoZGYubG9uZyRBYnVuZGFuY2UsIG5hLnJtID0gVFJVRSkKbWluKGRmLmxvbmckQWJ1bmRhbmNlLCBuYS5ybSA9IFRSVUUpCgoKIyBFeGFtcGxlIHVzYWdlCmhlYXRtYXBfcGxvdCA8LSBwbG90X2NsdXN0ZXJlZF9wcm90ZWluX2hlYXRtYXBfenNjb3JlKAogIGRhdGEgPSBkZiwKICBwcm90ZWlucyA9IGx5c29tZSRgR2VuZSBuYW1lYCwgIyBFeGFtcGxlIHByb3RlaW4gbmFtZXMKICBzYW1wbGVfcGF0dGVybnMgPSBjKCJDb250cm9sIiwgIkE1M1QiLCJHQkEuS08iLCJQSU5LMS5LTyIsIlBSS04uS08iLCJJTlBQNUYuS08iLCJJR1NGOUIuS08iLCAiU0gzR0wyLktPIiwiSVA2SzIuS08iKSwKICBjb2xvcnMgPSBjKCJzbm93IiwgImxpZ2h0Z29sZGVucm9kMSIsICJnb2xkMSIsICJkYXJrb3JhbmdlMSIsICJyZWQyIiwgImZpcmVicmljazQiKSwKICBzY2FsZV92YWx1ZXMgPSBjKC0xLjUsLTEsLTAuNSwgMCwgMiw0LjUpLCAjIEFkanVzdCBiYXNlZCBvbiB5b3VyIGRhdGEgcmFuZ2UKICBncm91cF9tZWFucyA9IFRSVUUsICMgU2V0IHRvIEZBTFNFIGlmIHlvdSB3YW50IGluZGl2aWR1YWwgc2FtcGxlcwogIGNlbGxfd2lkdGggPSAyMCwgIyBDb250cm9sIGNvbHVtbiB3aWR0aAogIGNlbGxfaGVpZ2h0ID0gMTAgIyBDb250cm9sIHJvdyBoZWlnaHQKKQoKCgojIEV4YW1wbGUgdXNhZ2UKaGVhdG1hcF9wbG90IDwtIHBsb3RfY2x1c3RlcmVkX3Byb3RlaW5faGVhdG1hcF96c2NvcmUoCiAgZGF0YSA9IGRmLAogIHByb3RlaW5zID0gbHlzb21lJGBHZW5lIG5hbWVgLCAgIyBFeGFtcGxlIHByb3RlaW4gbmFtZXMKICBzYW1wbGVfcGF0dGVybnMgPSBjKCJDb250cm9sLiIsICJBNTNULiIsIkdCQS5LTyIsIlBJTksxLktPIiwiUFJLTi5LTyIsIklOUFA1Ri5LTyIsIklHU0Y5Qi5LTyIsICJTSDNHTDIuS08iLCJJUDZLMi5LTyIpLAogIGNvbG9ycyA9IGMoInNub3ciLCAibGlnaHRnb2xkZW5yb2QxIiwgImdvbGQxIiwgImRhcmtvcmFuZ2UxIiwgInJlZDIiLCAiZmlyZWJyaWNrNCIpLAogIHNjYWxlX3ZhbHVlcyA9IGMoLTEsLTAuNSwgMCwgMi41LDUpLCAjIEFkanVzdCBiYXNlZCBvbiB5b3VyIGRhdGEgcmFuZ2UKICBncm91cF9tZWFucyA9IEZBTFNFLCAjIFNldCB0byBGQUxTRSBpZiB5b3Ugd2FudCBpbmRpdmlkdWFsIHNhbXBsZXMKICBjZWxsX3dpZHRoID0gMjAsICMgQ29udHJvbCBjb2x1bW4gd2lkdGgKICBjZWxsX2hlaWdodCA9IDEwICMgQ29udHJvbCByb3cgaGVpZ2h0CikKCgoKCmBgYAoKSGVhdCBtYXAgb2YgTG9nZm9sZCBjaGFuZ2UKCmBgYHtyfQoKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHRpZHlyKQoKIyBGdW5jdGlvbiB0byBwbG90IGEgaGVhdG1hcCBvZiBsb2ctZm9sZCBjaGFuZ2VzIGZvciBzZWxlY3RlZCBzYW1wbGVzIGFuZCBnZW5lcwpwbG90X2xvZ2ZvbGRfY2hhbmdlX2hlYXRtYXAgPC0gZnVuY3Rpb24oZmlsdGVyZWRfREVQLCBnZW5lX2xpc3QsIGNvbnRyYXN0X2xpc3QsIGNvbG9ycyA9IGMoImJsdWUiLCAid2hpdGUiLCAicmVkIiksIHJlbW92ZV9uYV9nZW5lcyA9IEZBTFNFKSB7CiAgIyBDaGVjayBpZiBhbGwgY29udHJhc3RzIGluIGNvbnRyYXN0X2xpc3QgZXhpc3QgaW4gZmlsdGVyZWRfREVQCiAgbWlzc2luZ19jb250cmFzdHMgPC0gc2V0ZGlmZihjb250cmFzdF9saXN0LCBuYW1lcyhmaWx0ZXJlZF9ERVApKQogIGlmIChsZW5ndGgobWlzc2luZ19jb250cmFzdHMpID4gMCkgewogICAgc3RvcChwYXN0ZSgiVGhlIGZvbGxvd2luZyBjb250cmFzdHMgYXJlIG5vdCBmb3VuZCBpbiBmaWx0ZXJlZF9ERVA6IiwgcGFzdGUobWlzc2luZ19jb250cmFzdHMsIGNvbGxhcHNlID0gIiwgIikpKQogIH0KCiAgIyBGaWx0ZXIgZGF0YSBmb3IgdGhlIHNlbGVjdGVkIGdlbmVzIGFuZCBjb250cmFzdHMKICBmaWx0ZXJlZF9kYXRhIDwtIGZpbHRlcmVkX0RFUFtjb250cmFzdF9saXN0XSAlPiUKICAgIGxhcHBseShmdW5jdGlvbihkZikgewogICAgICBkZiA8LSBhcy5kYXRhLmZyYW1lKGRmKSAgIyBDb252ZXJ0IHRvIGEgc3RhbmRhcmQgZGF0YSBmcmFtZQogICAgICBkZiAlPiUgCiAgICAgICAgZmlsdGVyKFN5bWJvbCAlaW4lIGdlbmVfbGlzdCkgJT4lIAogICAgICAgIGRwbHlyOjpzZWxlY3QoU3ltYm9sLCBsb2cyX3JhdGlvKSAgIyBVc2UgZHBseXI6OnNlbGVjdCB0byBhdm9pZCBjb25mbGljdHMKICAgIH0pCgogICMgQ29tYmluZSBhbGwgZmlsdGVyZWQgZGF0YSBpbnRvIG9uZSBkYXRhIGZyYW1lCiAgY29tYmluZWRfZGF0YSA8LSBiaW5kX3Jvd3MoZmlsdGVyZWRfZGF0YSwgLmlkID0gIkNvbnRyYXN0IikKCiAgIyBQaXZvdCBkYXRhIHRvIHdpZGUgZm9ybWF0IGZvciBlYXNpZXIgbWFuaXB1bGF0aW9uCiAgZGF0YV93aWRlIDwtIGNvbWJpbmVkX2RhdGEgJT4lCiAgICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gQ29udHJhc3QsIHZhbHVlc19mcm9tID0gbG9nMl9yYXRpbykgJT4lCiAgICBhcy5kYXRhLmZyYW1lKCkgICMgRW5zdXJlIGl0IGlzIGEgc3RhbmRhcmQgZGF0YSBmcmFtZQoKICAjIElmIHJlbW92ZV9uYV9nZW5lcyBpcyBUUlVFLCBmaWx0ZXIgb3V0IHJvd3Mgd2hlcmUgYWxsIGxvZzJGQyB2YWx1ZXMgYXJlIE5BCiAgaWYgKHJlbW92ZV9uYV9nZW5lcykgewogICAgZGF0YV93aWRlIDwtIGRhdGFfd2lkZSAlPiUKICAgICAgZmlsdGVyKHJvd1N1bXMoaXMubmEoZHBseXI6OnNlbGVjdCguLCAtU3ltYm9sKSkpIDwgKG5jb2woZGF0YV93aWRlKSAtIDEpKQogIH0KCiAgIyBQaXZvdCBkYXRhIGJhY2sgdG8gbG9uZyBmb3JtYXQgZm9yIGdncGxvdAogIGRhdGFfbG9uZyA8LSBkYXRhX3dpZGUgJT4lCiAgICBwaXZvdF9sb25nZXIoY29scyA9IC1TeW1ib2wsIG5hbWVzX3RvID0gIkNvbnRyYXN0IiwgdmFsdWVzX3RvID0gIkxvZzJGQyIpCgogICMgQ2FsY3VsYXRlIHRoZSBtYXhpbXVtIGFic29sdXRlIHZhbHVlIG9mIExvZzJGQyB0byBzZXQgc3ltbWV0cmljIGNvbG9yIGxpbWl0cwogIG1heF9hYnNfbG9nMmZjIDwtIG1heChhYnMoZGF0YV9sb25nJExvZzJGQyksIG5hLnJtID0gVFJVRSkKCiAgIyBDcmVhdGUgdGhlIGhlYXRtYXAgdXNpbmcgZ2dwbG90CiAgaGVhdG1hcF9wbG90IDwtIGdncGxvdChkYXRhX2xvbmcsIGFlcyh4ID0gQ29udHJhc3QsIHkgPSBTeW1ib2wsIGZpbGwgPSBMb2cyRkMpKSArCiAgICBnZW9tX3RpbGUoY29sb3IgPSAid2hpdGUiKSArCiAgICBzY2FsZV9maWxsX2dyYWRpZW50MigKICAgICAgbG93ID0gY29sb3JzWzFdLCBtaWQgPSBjb2xvcnNbMl0sIGhpZ2ggPSBjb2xvcnNbM10sIAogICAgICBtaWRwb2ludCA9IDAsIGxpbWl0cyA9IGMoLW1heF9hYnNfbG9nMmZjLCBtYXhfYWJzX2xvZzJmYyksIAogICAgICBvb2IgPSBzY2FsZXM6OnNxdWlzaCAjIGVuc3VyZXMgdmFsdWVzIG91dHNpZGUgdGhlIHJhbmdlIGFyZSBzcXVpc2hlZCB3aXRoaW4gdGhlIHNjYWxlCiAgICApICsKICAgIHRoZW1lX21pbmltYWwoKSArCiAgICB0aGVtZSgKICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgaGp1c3QgPSAxKSwKICAgICAgYXNwZWN0LnJhdGlvID0gbGVuZ3RoKHVuaXF1ZShkYXRhX2xvbmckU3ltYm9sKSkgLyBsZW5ndGgodW5pcXVlKGRhdGFfbG9uZyRDb250cmFzdCkpCiAgICApICsKICAgIGxhYnModGl0bGUgPSAiTG9nLUZvbGQgQ2hhbmdlIEhlYXRtYXAiLCB4ID0gIlNhbXBsZXMiLCB5ID0gIkdlbmVzIikKCiAgcmV0dXJuKGhlYXRtYXBfcGxvdCkKfQoKCgojIEV4YW1wbGUgdXNhZ2UKIyBEZWZpbmUgeW91ciBnZW5lIGxpc3QgYW5kIGNvbnRyYXN0cyBvZiBpbnRlcmVzdApnZW5lX2xpc3QgPC0gbHlzb21lJGBHZW5lIG5hbWVgCmNvbnRyYXN0X2xpc3QgPC0gYygiU05DQS1BNTNUIiwgIkdCQS1LTyIsICJQSU5LMS1LTyIsICJQUktOLUtPIiwiSUdTRjlCLUtPIiwiSU5QUDVGLUtPIiwiU0gzR0wyLUtPIiwiSVA2SzItS08iKQoKIyBDYWxsIHRoZSBmdW5jdGlvbiB0byBjcmVhdGUgYSBoZWF0bWFwCmhlYXRtYXBfcGxvdCA8LSBwbG90X2xvZ2ZvbGRfY2hhbmdlX2hlYXRtYXAoZGZfbGlzdCwgZ2VuZV9saXN0LCBjb250cmFzdF9saXN0LCByZW1vdmVfbmFfZ2VuZXMgPSBUUlVFKQoKIyBQcmludCB0aGUgaGVhdG1hcApwcmludChoZWF0bWFwX3Bsb3QpCgoKYGBgCgpTYW1lIGZ1bmN0aW9uIGJ1dCBjb250cm9saW5nIGtlZXBpbmcgdGhlIGdlbmUgbGlzdCBvcmRlcgoKYGBge3J9CmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShkcGx5cikKbGlicmFyeSh0aWR5cikKCiMgRnVuY3Rpb24gdG8gcGxvdCBhIGhlYXRtYXAgb2YgbG9nLWZvbGQgY2hhbmdlcyBmb3Igc2VsZWN0ZWQgc2FtcGxlcyBhbmQgZ2VuZXMKcGxvdF9sb2dmb2xkX2NoYW5nZV9oZWF0bWFwX29yZGVyZWQgPC0gZnVuY3Rpb24oZmlsdGVyZWRfREVQLCBnZW5lX2xpc3QsIGNvbnRyYXN0X2xpc3QsIGNvbG9ycyA9IGMoImJsdWUiLCAid2hpdGUiLCAicmVkIiksIHJlbW92ZV9uYV9nZW5lcyA9IEZBTFNFKSB7CiAgIyBDaGVjayBpZiBhbGwgY29udHJhc3RzIGluIGNvbnRyYXN0X2xpc3QgZXhpc3QgaW4gZmlsdGVyZWRfREVQCiAgbWlzc2luZ19jb250cmFzdHMgPC0gc2V0ZGlmZihjb250cmFzdF9saXN0LCBuYW1lcyhmaWx0ZXJlZF9ERVApKQogIGlmIChsZW5ndGgobWlzc2luZ19jb250cmFzdHMpID4gMCkgewogICAgc3RvcChwYXN0ZSgiVGhlIGZvbGxvd2luZyBjb250cmFzdHMgYXJlIG5vdCBmb3VuZCBpbiBmaWx0ZXJlZF9ERVA6IiwgcGFzdGUobWlzc2luZ19jb250cmFzdHMsIGNvbGxhcHNlID0gIiwgIikpKQogIH0KCiAgIyBGaWx0ZXIgZGF0YSBmb3IgdGhlIHNlbGVjdGVkIGdlbmVzIGFuZCBjb250cmFzdHMKICBmaWx0ZXJlZF9kYXRhIDwtIGZpbHRlcmVkX0RFUFtjb250cmFzdF9saXN0XSAlPiUKICAgIGxhcHBseShmdW5jdGlvbihkZikgewogICAgICBkZiA8LSBhcy5kYXRhLmZyYW1lKGRmKSAgIyBDb252ZXJ0IHRvIGEgc3RhbmRhcmQgZGF0YSBmcmFtZQogICAgICBkZiAlPiUgCiAgICAgICAgZmlsdGVyKFN5bWJvbCAlaW4lIGdlbmVfbGlzdCkgJT4lIAogICAgICAgIGRwbHlyOjpzZWxlY3QoU3ltYm9sLCBsb2cyX3JhdGlvKSAgIyBVc2UgZHBseXI6OnNlbGVjdCB0byBhdm9pZCBjb25mbGljdHMKICAgIH0pCgogICMgQ29tYmluZSBhbGwgZmlsdGVyZWQgZGF0YSBpbnRvIG9uZSBkYXRhIGZyYW1lCiAgY29tYmluZWRfZGF0YSA8LSBiaW5kX3Jvd3MoZmlsdGVyZWRfZGF0YSwgLmlkID0gIkNvbnRyYXN0IikKCiAgIyBQaXZvdCBkYXRhIHRvIHdpZGUgZm9ybWF0IGZvciBlYXNpZXIgbWFuaXB1bGF0aW9uCiAgZGF0YV93aWRlIDwtIGNvbWJpbmVkX2RhdGEgJT4lCiAgICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gQ29udHJhc3QsIHZhbHVlc19mcm9tID0gbG9nMl9yYXRpbykgJT4lCiAgICBhcy5kYXRhLmZyYW1lKCkgICMgRW5zdXJlIGl0IGlzIGEgc3RhbmRhcmQgZGF0YSBmcmFtZQoKICAjIElmIHJlbW92ZV9uYV9nZW5lcyBpcyBUUlVFLCBmaWx0ZXIgb3V0IHJvd3Mgd2hlcmUgYWxsIGxvZzJGQyB2YWx1ZXMgYXJlIE5BCiAgaWYgKHJlbW92ZV9uYV9nZW5lcykgewogICAgZGF0YV93aWRlIDwtIGRhdGFfd2lkZSAlPiUKICAgICAgZmlsdGVyKHJvd1N1bXMoaXMubmEoZHBseXI6OnNlbGVjdCguLCAtU3ltYm9sKSkpIDwgKG5jb2woZGF0YV93aWRlKSAtIDEpKQogIH0KCiAgIyBQaXZvdCBkYXRhIGJhY2sgdG8gbG9uZyBmb3JtYXQgZm9yIGdncGxvdAogIGRhdGFfbG9uZyA8LSBkYXRhX3dpZGUgJT4lCiAgICBwaXZvdF9sb25nZXIoY29scyA9IC1TeW1ib2wsIG5hbWVzX3RvID0gIkNvbnRyYXN0IiwgdmFsdWVzX3RvID0gIkxvZzJGQyIpCgogICMgU2V0IGZhY3RvciBsZXZlbHMgZm9yIGdlbmVzIGFuZCBjb250cmFzdHMgdG8gbWFpbnRhaW4gdGhlIHNwZWNpZmllZCBvcmRlcgogIGRhdGFfbG9uZyRTeW1ib2wgPC0gZmFjdG9yKGRhdGFfbG9uZyRTeW1ib2wsIGxldmVscyA9IGdlbmVfbGlzdCkKICBkYXRhX2xvbmckQ29udHJhc3QgPC0gZmFjdG9yKGRhdGFfbG9uZyRDb250cmFzdCwgbGV2ZWxzID0gY29udHJhc3RfbGlzdCkKCiAgIyBDYWxjdWxhdGUgdGhlIG1heGltdW0gYWJzb2x1dGUgdmFsdWUgb2YgTG9nMkZDIHRvIHNldCBzeW1tZXRyaWMgY29sb3IgbGltaXRzCiAgbWF4X2Fic19sb2cyZmMgPC0gbWF4KGFicyhkYXRhX2xvbmckTG9nMkZDKSwgbmEucm0gPSBUUlVFKQoKICAjIENyZWF0ZSB0aGUgaGVhdG1hcCB1c2luZyBnZ3Bsb3QKICBoZWF0bWFwX3Bsb3QgPC0gZ2dwbG90KGRhdGFfbG9uZywgYWVzKHggPSBDb250cmFzdCwgeSA9IFN5bWJvbCwgZmlsbCA9IExvZzJGQykpICsKICAgIGdlb21fdGlsZShjb2xvciA9ICJ3aGl0ZSIpICsKICAgIHNjYWxlX2ZpbGxfZ3JhZGllbnQyKAogICAgICBsb3cgPSBjb2xvcnNbMV0sIG1pZCA9IGNvbG9yc1syXSwgaGlnaCA9IGNvbG9yc1szXSwgCiAgICAgIG1pZHBvaW50ID0gMCwgbGltaXRzID0gYygtbWF4X2Fic19sb2cyZmMsIG1heF9hYnNfbG9nMmZjKSwgCiAgICAgIG9vYiA9IHNjYWxlczo6c3F1aXNoICMgZW5zdXJlcyB2YWx1ZXMgb3V0c2lkZSB0aGUgcmFuZ2UgYXJlIHNxdWlzaGVkIHdpdGhpbiB0aGUgc2NhbGUKICAgICkgKwogICAgdGhlbWVfbWluaW1hbCgpICsKICAgIHRoZW1lKAogICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpLAogICAgICBhc3BlY3QucmF0aW8gPSBsZW5ndGgodW5pcXVlKGRhdGFfbG9uZyRTeW1ib2wpKSAvIGxlbmd0aCh1bmlxdWUoZGF0YV9sb25nJENvbnRyYXN0KSkKICAgICkgKwogICAgbGFicyh0aXRsZSA9ICJMb2ctRm9sZCBDaGFuZ2UgSGVhdG1hcCAoT3JkZXJlZCkiLCB4ID0gIlNhbXBsZXMiLCB5ID0gIkdlbmVzIikKCiAgcmV0dXJuKGhlYXRtYXBfcGxvdCkKfQoKIyBFeGFtcGxlIHVzYWdlCiMgRGVmaW5lIHlvdXIgZ2VuZSBsaXN0IGFuZCBjb250cmFzdHMgb2YgaW50ZXJlc3QKZ2VuZV9saXN0IDwtIGx5c29tZSRgR2VuZSBuYW1lYApjb250cmFzdF9saXN0IDwtIGMoIlNOQ0EtQTUzVCIsICJHQkEtS08iLCAiUElOSzEtS08iLCAiUFJLTi1LTyIpCgojIENhbGwgdGhlIGZ1bmN0aW9uIHRvIGNyZWF0ZSBhIGhlYXRtYXAKaGVhdG1hcF9wbG90X29yZGVyZWQgPC0gcGxvdF9sb2dmb2xkX2NoYW5nZV9oZWF0bWFwX29yZGVyZWQoZGZfbGlzdF9udW1lcmljLCBnZW5lX2xpc3QsIGNvbnRyYXN0X2xpc3QsIHJlbW92ZV9uYV9nZW5lcyA9IFRSVUUpCgojIFByaW50IHRoZSBoZWF0bWFwCnByaW50KGhlYXRtYXBfcGxvdF9vcmRlcmVkKQoKYGBgCgpQbG90IGJ5IGRlbmRyb2dyYW0KCmBgYHtyfQpwbG90X2xvZ2ZvbGRfY2hhbmdlX2hlYXRtYXBfZGVuZHJvZ3JhbSA8LSBmdW5jdGlvbihkZl9saXN0LCBnZW5lX2xpc3QsIGNvbnRyYXN0X2xpc3QsIHJlbW92ZV9uYV9nZW5lcyA9IFRSVUUsIGNvbHVtbl93aWR0aCA9IDAuOCkgewogICMgRmlsdGVyIHRoZSBkYXRhZnJhbWVzIHRvIGluY2x1ZGUgb25seSB0aGUgc2VsZWN0ZWQgZ2VuZXMgYW5kIGNvbnRyYXN0cwogIGZpbHRlcmVkX2RhdGEgPC0gZGZfbGlzdFtjb250cmFzdF9saXN0XSAlPiUgCiAgICBsYXBwbHkoZnVuY3Rpb24oZGYpIHsKICAgICAgZGYgJT4lIAogICAgICAgIGRwbHlyOjpmaWx0ZXIoU3ltYm9sICVpbiUgZ2VuZV9saXN0KSAlPiUgCiAgICAgICAgZHBseXI6OnNlbGVjdChTeW1ib2wsIGxvZzJfcmF0aW8pCiAgICB9KSAlPiUgCiAgICBkcGx5cjo6YmluZF9yb3dzKC5pZCA9ICJDb250cmFzdCIpCiAgCiAgIyBDb252ZXJ0IHRvIGEgd2lkZSBmb3JtYXQgZm9yIHRoZSBoZWF0bWFwCiAgZGF0YV93aWRlIDwtIGZpbHRlcmVkX2RhdGEgJT4lCiAgICB0aWR5cjo6cGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IENvbnRyYXN0LCB2YWx1ZXNfZnJvbSA9IGxvZzJfcmF0aW8pCiAgCiAgIyBPcHRpb25hbGx5IHJlbW92ZSBnZW5lcyB3aXRoIGFsbCBOQSB2YWx1ZXMgYWNyb3NzIGNvbnRyYXN0cwogIGlmIChyZW1vdmVfbmFfZ2VuZXMpIHsKICAgIGRhdGFfd2lkZSA8LSBkYXRhX3dpZGUgJT4lCiAgICAgIGRwbHlyOjpmaWx0ZXIocm93U3Vtcyhpcy5uYShkcGx5cjo6c2VsZWN0KC4sIC1TeW1ib2wpKSkgPCBuY29sKGRhdGFfd2lkZSkgLSAxKQogIH0KICAKICAjIENvbnZlcnQgU3ltYm9sIHRvIHJvdyBuYW1lcyBmb3IgdGhlIGhlYXRtYXAKICBkYXRhX3dpZGUgPC0gZGF0YV93aWRlICU+JQogICAgdGliYmxlOjpjb2x1bW5fdG9fcm93bmFtZXMoIlN5bWJvbCIpCiAgCiAgIyBDcmVhdGUgYSBtYXRyaXggZm9yIHRoZSBoZWF0bWFwCiAgbWF0IDwtIGFzLm1hdHJpeChkYXRhX3dpZGUpCiAgCiAgIyBEZXRlcm1pbmUgdGhlIGxpbWl0cyBmb3IgdGhlIHNjYWxlIHRvIGJlIHN5bW1ldHJpYyBhcm91bmQgemVybwogIG1heF92YWwgPC0gbWF4KGFicyhtYXQpLCBuYS5ybSA9IFRSVUUpCiAgCiAgIyBQbG90IHRoZSBoZWF0bWFwIHdpdGggZGVuZHJvZ3JhbSBvcmRlcmluZwogIHBoZWF0bWFwOjpwaGVhdG1hcCgKICAgIG1hdCwKICAgIGNsdXN0ZXJfcm93cyA9IFRSVUUsCiAgICBjbHVzdGVyX2NvbHMgPSBUUlVFLAogICAgY29sb3IgPSBjb2xvclJhbXBQYWxldHRlKGMoImJsdWUiLCAid2hpdGUiLCAicmVkIikpKDEwMCksCiAgICBicmVha3MgPSBzZXEoLW1heF92YWwsIG1heF92YWwsIGxlbmd0aC5vdXQgPSAxMDEpLAogICAgY2VsbHdpZHRoID0gY29sdW1uX3dpZHRoLAogICAgY2VsbGhlaWdodCA9IGNvbHVtbl93aWR0aCwKICAgIG5hX2NvbCA9ICJncmV5IiwKICAgIHNjYWxlID0gIm5vbmUiICMgb3IgeW91IGNhbiB1c2UgInJvdyIgb3IgImNvbHVtbiIgaWYgc2NhbGluZyBpcyBuZWVkZWQKICApCn0KCgpwIDwtIHBsb3RfbG9nZm9sZF9jaGFuZ2VfaGVhdG1hcF9kZW5kcm9ncmFtKGRmX2xpc3RfbnVtZXJpYywgZ2VuZV9saXN0LCBjb250cmFzdF9saXN0LCByZW1vdmVfbmFfZ2VuZXMgPSBUUlVFLCBjb2x1bW5fd2lkdGggPSAxMCkKcHJpbnQocCkKCgoKYGBgCgpgYGB7ciwgZmlnLmhlaWdodD01fQoKCiMgbm93IHBsb3R0ZWQgd2l0aCBmdW5jdGlvbiBiZWxvdwoKZ2VuZV9saXN0IDwtIGx5c29tZSRgR2VuZSBuYW1lYApjb250cmFzdF9saXN0IDwtIGMoIlNOQ0EtQTUzVCIsICJHQkEtS08iLCAiUElOSzEtS08iLCAiUFJLTi1LTyIsICJJR1NGOUItS08iLCJJTlBQNUYtS08iLCJTSDNHTDItS08iLCJJUDZLMi1LTyIpCnAxIDwtIHBsb3RfbG9nZm9sZF9jaGFuZ2VfaGVhdG1hcF9kZW5kcm9ncmFtKGRmX2xpc3RfbnVtZXJpYywgZ2VuZV9saXN0LCBjb250cmFzdF9saXN0LCByZW1vdmVfbmFfZ2VuZXMgPSBUUlVFLCBjb2x1bW5fd2lkdGggPSAxKQpwcmludChwMSkKCgpnZW5lX2xpc3QgPC0gbHlzb21lJGBHZW5lIG5hbWVgCmNvbnRyYXN0X2xpc3QgPC0gYygiU05DQS1BNTNUIiwgIkdCQS1LTyIsICJQSU5LMS1LTyIsICJQUktOLUtPIikKcDIgPC0gcGxvdF9sb2dmb2xkX2NoYW5nZV9oZWF0bWFwX2RlbmRyb2dyYW0oZGZfbGlzdF9udW1lcmljLCBnZW5lX2xpc3QsIGNvbnRyYXN0X2xpc3QsIHJlbW92ZV9uYV9nZW5lcyA9IFRSVUUsIGNvbHVtbl93aWR0aCA9IDEpCnByaW50KHAyKQoKZ2VuZV9saXN0IDwtIGx5c29tZSRgR2VuZSBuYW1lYApjb250cmFzdF9saXN0IDwtIGMoIklHU0Y5Qi1LTyIsIklOUFA1Ri1LTyIsIlNIM0dMMi1LTyIsIklQNksyLUtPIikKcDMgPC0gcGxvdF9sb2dmb2xkX2NoYW5nZV9oZWF0bWFwX2RlbmRyb2dyYW0oZGZfbGlzdF9udW1lcmljLCBnZW5lX2xpc3QsIGNvbnRyYXN0X2xpc3QsIHJlbW92ZV9uYV9nZW5lcyA9IFRSVUUsIGNvbHVtbl93aWR0aCA9IDEpCnByaW50KHAzKQoKCmdlbmVfbGlzdCA8LSBseXNvbWUkYEdlbmUgbmFtZWAKY29udHJhc3RfbGlzdCA8LSBjKCJTTkNBLUE1M1QiLCAiR0JBLUtPIiwgIlBJTksxLUtPIiwgIlBSS04tS08iLCJJTlBQNUYtS08iLCJTSDNHTDItS08iLCJJUDZLMi1LTyIpCnA0IDwtIHBsb3RfbG9nZm9sZF9jaGFuZ2VfaGVhdG1hcF9kZW5kcm9ncmFtKGRmX2xpc3RfbnVtZXJpYywgZ2VuZV9saXN0LCBjb250cmFzdF9saXN0LCByZW1vdmVfbmFfZ2VuZXMgPSBUUlVFLCBjb2x1bW5fd2lkdGggPSAxKQpwcmludChwNCkKCgpgYGAKCgpgYGB7cn0KCgpnZW5lX2xpc3QgPC0gbHlzb21lJGBHZW5lIG5hbWVgCmNvbnRyYXN0X2xpc3QxIDwtIGMoIlNOQ0EtQTUzVCIsICJHQkEtS08iLCAiUElOSzEtS08iLCAiUFJLTi1LTyIsICJJR1NGOUItS08iLCJJTlBQNUYtS08iLCJTSDNHTDItS08iLCJJUDZLMi1LTyIpCmNvbnRyYXN0X2xpc3QyIDwtIGMoIlNOQ0EtQTUzVCIsICJHQkEtS08iLCAiUElOSzEtS08iLCAiUFJLTi1LTyIpCmNvbnRyYXN0X2xpc3QzIDwtIGMoIklHU0Y5Qi1LTyIsIklOUFA1Ri1LTyIsIlNIM0dMMi1LTyIsIklQNksyLUtPIikKY29udHJhc3RfbGlzdDQgPC0gYygiU05DQS1BNTNUIiwgIkdCQS1LTyIsICJQSU5LMS1LTyIsICJQUktOLUtPIiwiSU5QUDVGLUtPIiwiU0gzR0wyLUtPIiwiSVA2SzItS08iKQoKCgpwZGYoIi9Vc2Vycy9yaGFsZW5hdGhvbWFzL0Rvd25sb2Fkcy9Nb3ZlX0RhdGEvRGFya0dlbm9tZVJlc3VsdC9vbWljcy9ITV9seXNvbWVMaXN0X0xvZzJGQ19kZW5kcm9ncmFtLnBkZiIsIHdpZHRoID0gNiwgaGVpZ2h0ID0gOCkKcGxvdF9sb2dmb2xkX2NoYW5nZV9oZWF0bWFwX2RlbmRyb2dyYW0oZGZfbGlzdF9udW1lcmljLCBnZW5lX2xpc3QsIGNvbnRyYXN0X2xpc3QxLCByZW1vdmVfbmFfZ2VuZXMgPSBUUlVFLCBjb2x1bW5fd2lkdGggPSAxLCB0aXRsZSA9ICJMb2cgRm9sZCBDaGFuZ2UgTHlzb3NvbWUgR2VuZXMiKQpwbG90X2xvZ2ZvbGRfY2hhbmdlX2hlYXRtYXBfZGVuZHJvZ3JhbShkZl9saXN0X251bWVyaWMsIGdlbmVfbGlzdCwgY29udHJhc3RfbGlzdDEsIHJlbW92ZV9uYV9nZW5lcyA9IFRSVUUsIGNvbHVtbl93aWR0aCA9IDEsdGl0bGUgPSAiTG9nIEZvbGQgQ2hhbmdlIEx5c29zb21lIEdlbmVzIikKcGxvdF9sb2dmb2xkX2NoYW5nZV9oZWF0bWFwX2RlbmRyb2dyYW0oZGZfbGlzdF9udW1lcmljLCBnZW5lX2xpc3QsIGNvbnRyYXN0X2xpc3QzLCByZW1vdmVfbmFfZ2VuZXMgPSBUUlVFLCBjb2x1bW5fd2lkdGggPSAxLHRpdGxlID0gIkxvZyBGb2xkIENoYW5nZSBMeXNvc29tZSBHZW5lcyIpCnBsb3RfbG9nZm9sZF9jaGFuZ2VfaGVhdG1hcF9kZW5kcm9ncmFtKGRmX2xpc3RfbnVtZXJpYywgZ2VuZV9saXN0LCBjb250cmFzdF9saXN0NCwgcmVtb3ZlX25hX2dlbmVzID0gVFJVRSwgY29sdW1uX3dpZHRoID0gMSx0aXRsZSA9ICJMb2cgRm9sZCBDaGFuZ2UgTHlzb3NvbWUgR2VuZXMiKQpkZXYub2ZmKCkKCgpgYGAKCmdldCBhbm90aGVyIGdlbmUgbGlzdCBmcm9tIFJveGFubmUncyBsaXN0CgoKYGBge3J9Cm1pdG9jYXJ0YSA8LSByZWFkX2V4Y2VsKCIvVXNlcnMvcmhhbGVuYXRob21hcy9Eb3dubG9hZHMvTW92ZV9EYXRhL0RhcmtHZW5vbWVSZXN1bHQvTGlzdCBvZiBnZW5lcyBmb3IgUk5Bc2VxIG9yIFByb3Rlb21pY3MvTWl0b0NhcnRhMy4wLnhsc3giKQoKbWl0by5nZW5lcyA8LSBtaXRvY2FydGEkU3ltYm9sCmxlbmd0aChtaXRvLmdlbmVzKQoKCmBgYApgYGB7cn0KCmdlbmVfbGlzdCA8LSBtaXRvLmdlbmVzWzE6MjBdCiNnZW5lX2xpc3QgPC0gbHlzb21lJGBHZW5lIG5hbWVgCmNvbnRyYXN0X2xpc3QgPC0gYygiU05DQS1BNTNUIiwgIkdCQS1LTyIsICJQSU5LMS1LTyIsICJQUktOLUtPIiwgIklHU0Y5Qi1LTyIsIklOUFA1Ri1LTyIsIlNIM0dMMi1LTyIsIklQNksyLUtPIikKcDEgPC0gcGxvdF9sb2dmb2xkX2NoYW5nZV9oZWF0bWFwX2RlbmRyb2dyYW0oZGZfbGlzdF9udW1lcmljLCBnZW5lX2xpc3QsIGNvbnRyYXN0X2xpc3QsIHJlbW92ZV9uYV9nZW5lcyA9IFRSVUUsIGNvbHVtbl93aWR0aCA9IDEyKQpwcmludChwMSkKCgpjb250cmFzdF9saXN0IDwtIGMoIlNOQ0EtQTUzVCIsICJHQkEtS08iLCAiUElOSzEtS08iLCAiUFJLTi1LTyIpCnAyIDwtIHBsb3RfbG9nZm9sZF9jaGFuZ2VfaGVhdG1hcF9kZW5kcm9ncmFtKGRmX2xpc3RfbnVtZXJpYywgZ2VuZV9saXN0LCBjb250cmFzdF9saXN0LCByZW1vdmVfbmFfZ2VuZXMgPSBUUlVFLCBjb2x1bW5fd2lkdGggPSAxMikKcHJpbnQocDIpCgpjb250cmFzdF9saXN0IDwtIGMoIklHU0Y5Qi1LTyIsIklOUFA1Ri1LTyIsIlNIM0dMMi1LTyIsIklQNksyLUtPIikKcDMgPC0gcGxvdF9sb2dmb2xkX2NoYW5nZV9oZWF0bWFwX2RlbmRyb2dyYW0oZGZfbGlzdF9udW1lcmljLCBnZW5lX2xpc3QsIGNvbnRyYXN0X2xpc3QsIHJlbW92ZV9uYV9nZW5lcyA9IFRSVUUsIGNvbHVtbl93aWR0aCA9IDEyKQpwcmludChwMykKCmNvbnRyYXN0X2xpc3QgPC0gYygiU05DQS1BNTNUIiwgIkdCQS1LTyIsICJQSU5LMS1LTyIsICJQUktOLUtPIiwiSU5QUDVGLUtPIiwiU0gzR0wyLUtPIiwiSVA2SzItS08iKQpwNCA8LSBwbG90X2xvZ2ZvbGRfY2hhbmdlX2hlYXRtYXBfZGVuZHJvZ3JhbShkZl9saXN0X251bWVyaWMsIGdlbmVfbGlzdCwgY29udHJhc3RfbGlzdCwgcmVtb3ZlX25hX2dlbmVzID0gVFJVRSwgY29sdW1uX3dpZHRoID0gMTIpCnByaW50KHA0KQoKYGBgCgpOZXcgZnVuY3Rpb24gdG8gc2tpcCBnZW5lcyBub3QgZm91bmQgaW4gZGZfbGlzdAoKYGBge3J9CgpwbG90X2xvZ2ZvbGRfY2hhbmdlX2hlYXRtYXBfZGVuZHJvZ3JhbSA8LSBmdW5jdGlvbihkZl9saXN0LCBnZW5lX2xpc3QsIGNvbnRyYXN0X2xpc3QsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVfbmFfZ2VuZXMgPSBGQUxTRSwgY29sdW1uX3dpZHRoID0gMC44KSB7CiAgIyBGaWx0ZXIgZGF0YSB0byBvbmx5IGluY2x1ZGUgdGhlIHNwZWNpZmllZCBnZW5lcyBhbmQgY29udHJhc3RzCiAgZmlsdGVyZWRfZGF0YSA8LSBkZl9saXN0W2NvbnRyYXN0X2xpc3RdICU+JQogICAgbGFwcGx5KGZ1bmN0aW9uKGRmKSB7CiAgICAgIGRmICU+JSAKICAgICAgICBkcGx5cjo6ZmlsdGVyKFN5bWJvbCAlaW4lIGdlbmVfbGlzdCkgJT4lIAogICAgICAgIGRwbHlyOjpzZWxlY3QoU3ltYm9sLCBsb2cyX3JhdGlvKQogICAgfSkgJT4lIAogICAgZHBseXI6OmJpbmRfcm93cyguaWQgPSAiQ29udHJhc3QiKQogIAogICMgRW5zdXJlIG9ubHkgZ2VuZXMgaW4gZ2VuZV9saXN0IHRoYXQgYXJlIGZvdW5kIGluIHRoZSBmaWx0ZXJlZCBkYXRhIGFyZSBrZXB0CiAgZmlsdGVyZWRfZGF0YSA8LSBmaWx0ZXJlZF9kYXRhICU+JQogICAgZHBseXI6OmZpbHRlcihTeW1ib2wgJWluJSB1bmlxdWUoZmlsdGVyZWRfZGF0YSRTeW1ib2wpKQogIAogICMgQ3JlYXRlIGEgd2lkZSBmb3JtYXQgbWF0cml4IGZvciBoZWF0bWFwIHBsb3R0aW5nCiAgZGF0YV93aWRlIDwtIGZpbHRlcmVkX2RhdGEgJT4lCiAgICB0aWR5cjo6cGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IENvbnRyYXN0LCB2YWx1ZXNfZnJvbSA9IGxvZzJfcmF0aW8pICU+JQogICAgZHBseXI6OmZpbHRlcihTeW1ib2wgJWluJSBnZW5lX2xpc3QpICU+JSAjIEVuc3VyZSBvbmx5IGdlbmVzIGluIGdlbmVfbGlzdCBhcmUga2VwdAogICAgZHBseXI6Om11dGF0ZShhY3Jvc3MoLVN5bWJvbCwgYXMubnVtZXJpYykpCgogICMgT3B0aW9uYWxseSByZW1vdmUgZ2VuZXMgdGhhdCBhcmUgTkEgYWNyb3NzIGFsbCBjb250cmFzdHMKICBpZiAocmVtb3ZlX25hX2dlbmVzKSB7CiAgICBkYXRhX3dpZGUgPC0gZGF0YV93aWRlICU+JQogICAgICBkcGx5cjo6ZmlsdGVyKHJvd1N1bXMoaXMubmEoZHBseXI6OnNlbGVjdCguLCAtU3ltYm9sKSkpIDwgbmNvbChkYXRhX3dpZGUpIC0gMSkKICB9CgogICMgQ3JlYXRlIGEgbWF0cml4IGZvciBoZWF0bWFwIHBsb3R0aW5nCiAgbWF0IDwtIGFzLm1hdHJpeChkYXRhX3dpZGUgJT4lIGRwbHlyOjpzZWxlY3QoLVN5bWJvbCkpCiAgcm93bmFtZXMobWF0KSA8LSBkYXRhX3dpZGUkU3ltYm9sCiAgCiAgIyBDcmVhdGUgdGhlIGhlYXRtYXAgd2l0aCBkZW5kcm9ncmFtcwogIHBoZWF0bWFwOjpwaGVhdG1hcChtYXQsIAogICAgICAgICAgICAgICAgICAgICBjbHVzdGVyX3Jvd3MgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgY2x1c3Rlcl9jb2xzID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgIHNjYWxlID0gIm5vbmUiLCAKICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSBjb2xvclJhbXBQYWxldHRlKGMoImJsdWUiLCAid2hpdGUiLCAicmVkIikpKDUwKSwKICAgICAgICAgICAgICAgICAgICAgY2VsbHdpZHRoID0gY29sdW1uX3dpZHRoICogMTAsICMgQWRqdXN0IGNvbHVtbiB3aWR0aAogICAgICAgICAgICAgICAgICAgICBzaG93X3Jvd25hbWVzID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgc2hvd19jb2xuYW1lcyA9IFRSVUUpCn0KCiMgRXhhbXBsZSB1c2FnZQoKCgpnZW5lX2xpc3QgPC0gbWl0b2NhcnRhJFN5bWJvbFsxMToyMF0KcHJpbnQoZ2VuZV9saXN0KQoKY29udHJhc3RfbGlzdCA8LSBjKCJTTkNBLUE1M1QiLCAiR0JBLUtPIiwgIlBJTksxLUtPIiwgIlBSS04tS08iLCAiSUdTRjlCLUtPIiwiSU5QUDVGLUtPIiwiU0gzR0wyLUtPIiwiSVA2SzItS08iKQpwbG90X2xvZ2ZvbGRfY2hhbmdlX2hlYXRtYXBfZGVuZHJvZ3JhbShkZl9saXN0X251bWVyaWMsIGdlbmVfbGlzdCA9IGMoIlBJTksxIiwiR0ZBUCIsIlMxMDBCIiwiU05DQSIsIlZNQVQyIiwiR0xVVDIiLCJQUktOIiksIGNvbnRyYXN0X2xpc3QsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVfbmFfZ2VuZXMgPSBUUlVFLCBjb2x1bW5fd2lkdGggPSAxKQoKcGxvdF9sb2dmb2xkX2NoYW5nZV9oZWF0bWFwX2RlbmRyb2dyYW0oZGZfbGlzdF9udW1lcmljLCBnZW5lX2xpc3QgPSBtaXRvY2FydGEkU3ltYm9sWzE6MTBdLCBjb250cmFzdF9saXN0LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlX25hX2dlbmVzID0gVFJVRSwgY29sdW1uX3dpZHRoID0gMSkKCgpwbG90X2xvZ2ZvbGRfY2hhbmdlX2hlYXRtYXBfZGVuZHJvZ3JhbShkZl9saXN0X251bWVyaWMsIGdlbmVfbGlzdCA9IG1pdG9jYXJ0YSRTeW1ib2xbMTE6MjBdLCBjb250cmFzdF9saXN0LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlX25hX2dlbmVzID0gVFJVRSwgY29sdW1uX3dpZHRoID0gMSkKCnByaW50KG1pdG9jYXJ0YSRTeW1ib2xbMToxMV0pCnByaW50KG1pdG9jYXJ0YSRTeW1ib2xbMTE6MjBdKQoKYGBgCgpUaGlzIGVycm9yIHNlZW1zIHRvIG1lYW4gdGhlcmUgYXJlIGR1cGxpY2F0ZSBlbnRlcmllcyBmb3IgdGhlIHNhbWUgZ2VuZQoKYGBge3J9CgpwbG90X2xvZ2ZvbGRfY2hhbmdlX2hlYXRtYXBfZGVuZHJvZ3JhbSA8LSBmdW5jdGlvbihkZl9saXN0LCBnZW5lX2xpc3QsIGNvbnRyYXN0X2xpc3QsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVfbmFfZ2VuZXMgPSBGQUxTRSwgY29sdW1uX3dpZHRoID0gMC44KSB7CiAgIyBGaWx0ZXIgZGF0YSB0byBvbmx5IGluY2x1ZGUgdGhlIHNwZWNpZmllZCBnZW5lcyBhbmQgY29udHJhc3RzCiAgZmlsdGVyZWRfZGF0YSA8LSBkZl9saXN0W2NvbnRyYXN0X2xpc3RdICU+JQogICAgbGFwcGx5KGZ1bmN0aW9uKGRmKSB7CiAgICAgIGRmICU+JSAKICAgICAgICBkcGx5cjo6ZmlsdGVyKFN5bWJvbCAlaW4lIGdlbmVfbGlzdCkgJT4lIAogICAgICAgIGRwbHlyOjpzZWxlY3QoU3ltYm9sLCBsb2cyX3JhdGlvKQogICAgfSkgJT4lIAogICAgZHBseXI6OmJpbmRfcm93cyguaWQgPSAiQ29udHJhc3QiKQogIAogICMgRW5zdXJlIG9ubHkgZ2VuZXMgaW4gZ2VuZV9saXN0IHRoYXQgYXJlIGZvdW5kIGluIHRoZSBmaWx0ZXJlZCBkYXRhIGFyZSBrZXB0CiAgZmlsdGVyZWRfZGF0YSA8LSBmaWx0ZXJlZF9kYXRhICU+JQogICAgZHBseXI6OmZpbHRlcihTeW1ib2wgJWluJSB1bmlxdWUoZmlsdGVyZWRfZGF0YSRTeW1ib2wpKQogIAogICMgSGFuZGxlIGR1cGxpY2F0ZXMgYnkgc3VtbWFyaXppbmcgKGUuZy4sIHRha2luZyB0aGUgbWVhbikKICBmaWx0ZXJlZF9kYXRhIDwtIGZpbHRlcmVkX2RhdGEgJT4lCiAgICBkcGx5cjo6Z3JvdXBfYnkoU3ltYm9sLCBDb250cmFzdCkgJT4lCiAgICBkcGx5cjo6c3VtbWFyaXplKGxvZzJfcmF0aW8gPSBtZWFuKGxvZzJfcmF0aW8sIG5hLnJtID0gVFJVRSksIC5ncm91cHMgPSAnZHJvcCcpCiAgCiAgIyBDcmVhdGUgYSB3aWRlIGZvcm1hdCBtYXRyaXggZm9yIGhlYXRtYXAgcGxvdHRpbmcKICBkYXRhX3dpZGUgPC0gZmlsdGVyZWRfZGF0YSAlPiUKICAgIHRpZHlyOjpwaXZvdF93aWRlcihuYW1lc19mcm9tID0gQ29udHJhc3QsIHZhbHVlc19mcm9tID0gbG9nMl9yYXRpbykgJT4lCiAgICBkcGx5cjo6ZmlsdGVyKFN5bWJvbCAlaW4lIGdlbmVfbGlzdCkgJT4lICMgRW5zdXJlIG9ubHkgZ2VuZXMgaW4gZ2VuZV9saXN0IGFyZSBrZXB0CiAgICBkcGx5cjo6bXV0YXRlKGRwbHlyOjphY3Jvc3MoLVN5bWJvbCwgYXMubnVtZXJpYykpCgogICMgT3B0aW9uYWxseSByZW1vdmUgZ2VuZXMgdGhhdCBhcmUgTkEgYWNyb3NzIGFsbCBjb250cmFzdHMKICBpZiAocmVtb3ZlX25hX2dlbmVzKSB7CiAgICBkYXRhX3dpZGUgPC0gZGF0YV93aWRlICU+JQogICAgICBkcGx5cjo6ZmlsdGVyKHJvd1N1bXMoaXMubmEoZHBseXI6OnNlbGVjdCguLCAtU3ltYm9sKSkpIDwgbmNvbChkYXRhX3dpZGUpIC0gMSkKICB9CgogICMgQ3JlYXRlIGEgbWF0cml4IGZvciBoZWF0bWFwIHBsb3R0aW5nCiAgbWF0IDwtIGFzLm1hdHJpeChkYXRhX3dpZGUgJT4lIGRwbHlyOjpzZWxlY3QoLVN5bWJvbCkpCiAgcm93bmFtZXMobWF0KSA8LSBkYXRhX3dpZGUkU3ltYm9sCiAgCiAgIyBDcmVhdGUgdGhlIGhlYXRtYXAgd2l0aCBkZW5kcm9ncmFtcwogIHBoZWF0bWFwOjpwaGVhdG1hcChtYXQsIAogICAgICAgICAgICAgICAgICAgICBjbHVzdGVyX3Jvd3MgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgY2x1c3Rlcl9jb2xzID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgIHNjYWxlID0gIm5vbmUiLCAKICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSBjb2xvclJhbXBQYWxldHRlKGMoImJsdWUiLCAid2hpdGUiLCAicmVkIikpKDUwKSwKICAgICAgICAgICAgICAgICAgICAgY2VsbHdpZHRoID0gY29sdW1uX3dpZHRoICogMTAsICMgQWRqdXN0IGNvbHVtbiB3aWR0aAogICAgICAgICAgICAgICAgICAgICBzaG93X3Jvd25hbWVzID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgc2hvd19jb2xuYW1lcyA9IFRSVUUpCn0KCgpwbG90X2xvZ2ZvbGRfY2hhbmdlX2hlYXRtYXBfZGVuZHJvZ3JhbShkZl9saXN0X251bWVyaWMsIGdlbmVfbGlzdCA9IG1pdG9jYXJ0YSRTeW1ib2xbMToxMF0sIGNvbnRyYXN0X2xpc3QsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVfbmFfZ2VuZXMgPSBUUlVFLCBjb2x1bW5fd2lkdGggPSAxKQoKCnBsb3RfbG9nZm9sZF9jaGFuZ2VfaGVhdG1hcF9kZW5kcm9ncmFtKGRmX2xpc3RfbnVtZXJpYywgZ2VuZV9saXN0ID0gbWl0b2NhcnRhJFN5bWJvbFsxMDoyMF0sIGNvbnRyYXN0X2xpc3QsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVfbmFfZ2VuZXMgPSBUUlVFLCBjb2x1bW5fd2lkdGggPSAxKQoKCgpwbG90X2xvZ2ZvbGRfY2hhbmdlX2hlYXRtYXBfZGVuZHJvZ3JhbShkZl9saXN0X251bWVyaWMsIGdlbmVfbGlzdCA9IG1pdG9jYXJ0YSRTeW1ib2xbMTE6NjBdLCBjb250cmFzdF9saXN0LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlX25hX2dlbmVzID0gVFJVRSwgY29sdW1uX3dpZHRoID0gMC44KQoKCnBsb3RfbG9nZm9sZF9jaGFuZ2VfaGVhdG1hcF9kZW5kcm9ncmFtKGRmX2xpc3RfbnVtZXJpYywgZ2VuZV9saXN0ID0gbWl0b2NhcnRhJFN5bWJvbFsxOjIwXSwgY29udHJhc3RfbGlzdCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZV9uYV9nZW5lcyA9IFRSVUUsIGNvbHVtbl93aWR0aCA9IDEpCgoKYGBgCldlIG5vdyBuZWVkIHRvIHJlbW92ZSBwcm9ibGVtYXRpYyB2YWx1ZXMgCgpgYGB7cn0KcGxvdF9sb2dmb2xkX2NoYW5nZV9oZWF0bWFwX2RlbmRyb2dyYW0gPC0gZnVuY3Rpb24oZGZfbGlzdCwgZ2VuZV9saXN0LCBjb250cmFzdF9saXN0LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlX25hX2dlbmVzID0gRkFMU0UsIGNvbHVtbl93aWR0aCA9IDAuOCkgewogICMgRmlsdGVyIGRhdGEgdG8gb25seSBpbmNsdWRlIHRoZSBzcGVjaWZpZWQgZ2VuZXMgYW5kIGNvbnRyYXN0cwogIGZpbHRlcmVkX2RhdGEgPC0gZGZfbGlzdFtjb250cmFzdF9saXN0XSAlPiUKICAgIGxhcHBseShmdW5jdGlvbihkZikgewogICAgICBkZiAlPiUgCiAgICAgICAgZHBseXI6OmZpbHRlcihTeW1ib2wgJWluJSBnZW5lX2xpc3QpICU+JSAKICAgICAgICBkcGx5cjo6c2VsZWN0KFN5bWJvbCwgbG9nMl9yYXRpbykKICAgIH0pICU+JSAKICAgIGRwbHlyOjpiaW5kX3Jvd3MoLmlkID0gIkNvbnRyYXN0IikKICAKICAjIEVuc3VyZSBvbmx5IGdlbmVzIGluIGdlbmVfbGlzdCB0aGF0IGFyZSBmb3VuZCBpbiB0aGUgZmlsdGVyZWQgZGF0YSBhcmUga2VwdAogIGZpbHRlcmVkX2RhdGEgPC0gZmlsdGVyZWRfZGF0YSAlPiUKICAgIGRwbHlyOjpmaWx0ZXIoU3ltYm9sICVpbiUgdW5pcXVlKGZpbHRlcmVkX2RhdGEkU3ltYm9sKSkKICAKICAjIEhhbmRsZSBkdXBsaWNhdGVzIGJ5IHN1bW1hcml6aW5nIChlLmcuLCB0YWtpbmcgdGhlIG1lYW4pCiAgZmlsdGVyZWRfZGF0YSA8LSBmaWx0ZXJlZF9kYXRhICU+JQogICAgZHBseXI6Omdyb3VwX2J5KFN5bWJvbCwgQ29udHJhc3QpICU+JQogICAgZHBseXI6OnN1bW1hcml6ZShsb2cyX3JhdGlvID0gbWVhbihsb2cyX3JhdGlvLCBuYS5ybSA9IFRSVUUpLCAuZ3JvdXBzID0gJ2Ryb3AnKQogIAogICMgQ3JlYXRlIGEgd2lkZSBmb3JtYXQgbWF0cml4IGZvciBoZWF0bWFwIHBsb3R0aW5nCiAgZGF0YV93aWRlIDwtIGZpbHRlcmVkX2RhdGEgJT4lCiAgICB0aWR5cjo6cGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IENvbnRyYXN0LCB2YWx1ZXNfZnJvbSA9IGxvZzJfcmF0aW8pICU+JQogICAgZHBseXI6OmZpbHRlcihTeW1ib2wgJWluJSBnZW5lX2xpc3QpICU+JSAjIEVuc3VyZSBvbmx5IGdlbmVzIGluIGdlbmVfbGlzdCBhcmUga2VwdAogICAgZHBseXI6Om11dGF0ZShkcGx5cjo6YWNyb3NzKC1TeW1ib2wsIGFzLm51bWVyaWMpKQoKICAjIE9wdGlvbmFsbHkgcmVtb3ZlIGdlbmVzIHRoYXQgYXJlIE5BIGFjcm9zcyBhbGwgY29udHJhc3RzCiAgaWYgKHJlbW92ZV9uYV9nZW5lcykgewogICAgZGF0YV93aWRlIDwtIGRhdGFfd2lkZSAlPiUKICAgICAgZHBseXI6OmZpbHRlcihyb3dTdW1zKGlzLm5hKGRwbHlyOjpzZWxlY3QoLiwgLVN5bWJvbCkpKSA8IG5jb2woZGF0YV93aWRlKSAtIDEpCiAgfQoKICAjIENyZWF0ZSBhIG1hdHJpeCBmb3IgaGVhdG1hcCBwbG90dGluZwogIG1hdCA8LSBhcy5tYXRyaXgoZGF0YV93aWRlICU+JSBkcGx5cjo6c2VsZWN0KC1TeW1ib2wpKQogIHJvd25hbWVzKG1hdCkgPC0gZGF0YV93aWRlJFN5bWJvbAogIAogICMgQ2hlY2sgZm9yIE5BLCBOYU4sIG9yIEluZiB2YWx1ZXMgaW4gdGhlIG1hdHJpeCBhbmQgcmVtb3ZlIGFueSByb3dzIG9yIGNvbHVtbnMgdGhhdCBjb250YWluIHRoZW0KICBtYXQgPC0gbWF0W2NvbXBsZXRlLmNhc2VzKG1hdCksIF0gICMgUmVtb3ZlIHJvd3Mgd2l0aCBOQS9OYU4vSW5mIHZhbHVlcwogIG1hdCA8LSBtYXRbLCBjb2xTdW1zKGlzLm5hKG1hdCkpID09IDBdICAjIFJlbW92ZSBjb2x1bW5zIHdpdGggTkEvTmFOL0luZiB2YWx1ZXMKICAKICAjIElmIGFmdGVyIHJlbW92aW5nIE5BIHJvd3MvY29sdW1ucyB0aGUgbWF0cml4IGJlY29tZXMgZW1wdHksIHJldHVybiBhbiBpbmZvcm1hdGl2ZSBlcnJvcgogIGlmIChucm93KG1hdCkgPT0gMCB8fCBuY29sKG1hdCkgPT0gMCkgewogICAgc3RvcCgiVGhlIG1hdHJpeCBpcyBlbXB0eSBhZnRlciByZW1vdmluZyByb3dzL2NvbHVtbnMgd2l0aCBOQS9OYU4vSW5mIHZhbHVlcy4gTm8gdmFsaWQgZGF0YSB0byBwbG90LiIpCiAgfQogIAogICMgQ3JlYXRlIHRoZSBoZWF0bWFwIHdpdGggZGVuZHJvZ3JhbXMKICBwaGVhdG1hcDo6cGhlYXRtYXAobWF0LCAKICAgICAgICAgICAgICAgICAgICAgY2x1c3Rlcl9yb3dzID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgIGNsdXN0ZXJfY29scyA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICBzY2FsZSA9ICJub25lIiwgCiAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gY29sb3JSYW1wUGFsZXR0ZShjKCJibHVlIiwgIndoaXRlIiwgInJlZCIpKSg1MCksCiAgICAgICAgICAgICAgICAgICAgIGNlbGx3aWR0aCA9IGNvbHVtbl93aWR0aCAqIDEwLCAjIEFkanVzdCBjb2x1bW4gd2lkdGgKICAgICAgICAgICAgICAgICAgICAgc2hvd19yb3duYW1lcyA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgIHNob3dfY29sbmFtZXMgPSBUUlVFKQp9CgpwbG90X2xvZ2ZvbGRfY2hhbmdlX2hlYXRtYXBfZGVuZHJvZ3JhbShkZl9saXN0X251bWVyaWMsIGdlbmVfbGlzdCA9IG1pdG9jYXJ0YSRTeW1ib2xbMToxMF0sIGNvbnRyYXN0X2xpc3QsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVfbmFfZ2VuZXMgPSBUUlVFLCBjb2x1bW5fd2lkdGggPSAxKQoKCnBsb3RfbG9nZm9sZF9jaGFuZ2VfaGVhdG1hcF9kZW5kcm9ncmFtKGRmX2xpc3RfbnVtZXJpYywgZ2VuZV9saXN0ID0gbWl0b2NhcnRhJFN5bWJvbFsxMDoyMF0sIGNvbnRyYXN0X2xpc3QsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVfbmFfZ2VuZXMgPSBUUlVFLCBjb2x1bW5fd2lkdGggPSAxKQoKCgpwbG90X2xvZ2ZvbGRfY2hhbmdlX2hlYXRtYXBfZGVuZHJvZ3JhbShkZl9saXN0X251bWVyaWMsIGdlbmVfbGlzdCA9IG1pdG9jYXJ0YSRTeW1ib2xbMTE6NjBdLCBjb250cmFzdF9saXN0LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlX25hX2dlbmVzID0gVFJVRSwgY29sdW1uX3dpZHRoID0gMC44KQoKCnBsb3RfbG9nZm9sZF9jaGFuZ2VfaGVhdG1hcF9kZW5kcm9ncmFtKGRmX2xpc3RfbnVtZXJpYywgZ2VuZV9saXN0ID0gbWl0b2NhcnRhJFN5bWJvbFsxOjIwXSwgY29udHJhc3RfbGlzdCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZV9uYV9nZW5lcyA9IFRSVUUsIGNvbHVtbl93aWR0aCA9IDEpCgpwbG90X2xvZ2ZvbGRfY2hhbmdlX2hlYXRtYXBfZGVuZHJvZ3JhbShkZl9saXN0X251bWVyaWMsIGdlbmVfbGlzdCA9IG1pdG9jYXJ0YSRTeW1ib2wsIGNvbnRyYXN0X2xpc3QsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVfbmFfZ2VuZXMgPSBUUlVFLCBjb2x1bW5fd2lkdGggPSAxKQoKCmBgYApGb3JjZSAwIHRvIGJlIHRoZSBjZW50ZXIgb2YgdGhlIHNjYWxlCgoKYGBge3J9CnBsb3RfbG9nZm9sZF9jaGFuZ2VfaGVhdG1hcF9kZW5kcm9ncmFtIDwtIGZ1bmN0aW9uKGRmX2xpc3QsIGdlbmVfbGlzdCwgY29udHJhc3RfbGlzdCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZV9uYV9nZW5lcyA9IEZBTFNFLCBjb2x1bW5fd2lkdGggPSAwLjgsIHRpdGxlID0gIkxvZyBGb2xkIENoYW5nZSIpIHsKICAjIEZpbHRlciBkYXRhIHRvIG9ubHkgaW5jbHVkZSB0aGUgc3BlY2lmaWVkIGdlbmVzIGFuZCBjb250cmFzdHMKICBmaWx0ZXJlZF9kYXRhIDwtIGRmX2xpc3RbY29udHJhc3RfbGlzdF0gJT4lCiAgICBsYXBwbHkoZnVuY3Rpb24oZGYpIHsKICAgICAgZGYgJT4lIAogICAgICAgIGRwbHlyOjpmaWx0ZXIoU3ltYm9sICVpbiUgZ2VuZV9saXN0KSAlPiUgCiAgICAgICAgZHBseXI6OnNlbGVjdChTeW1ib2wsIGxvZzJfcmF0aW8pCiAgICB9KSAlPiUgCiAgICBkcGx5cjo6YmluZF9yb3dzKC5pZCA9ICJDb250cmFzdCIpCiAgCiAgIyBFbnN1cmUgb25seSBnZW5lcyBpbiBnZW5lX2xpc3QgdGhhdCBhcmUgZm91bmQgaW4gdGhlIGZpbHRlcmVkIGRhdGEgYXJlIGtlcHQKICBmaWx0ZXJlZF9kYXRhIDwtIGZpbHRlcmVkX2RhdGEgJT4lCiAgICBkcGx5cjo6ZmlsdGVyKFN5bWJvbCAlaW4lIHVuaXF1ZShmaWx0ZXJlZF9kYXRhJFN5bWJvbCkpCiAgCiAgIyBIYW5kbGUgZHVwbGljYXRlcyBieSBzdW1tYXJpemluZyAoZS5nLiwgdGFraW5nIHRoZSBtZWFuKQogIGZpbHRlcmVkX2RhdGEgPC0gZmlsdGVyZWRfZGF0YSAlPiUKICAgIGRwbHlyOjpncm91cF9ieShTeW1ib2wsIENvbnRyYXN0KSAlPiUKICAgIGRwbHlyOjpzdW1tYXJpemUobG9nMl9yYXRpbyA9IG1lYW4obG9nMl9yYXRpbywgbmEucm0gPSBUUlVFKSwgLmdyb3VwcyA9ICdkcm9wJykKICAKICAjIENyZWF0ZSBhIHdpZGUgZm9ybWF0IG1hdHJpeCBmb3IgaGVhdG1hcCBwbG90dGluZwogIGRhdGFfd2lkZSA8LSBmaWx0ZXJlZF9kYXRhICU+JQogICAgdGlkeXI6OnBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBDb250cmFzdCwgdmFsdWVzX2Zyb20gPSBsb2cyX3JhdGlvKSAlPiUKICAgIGRwbHlyOjpmaWx0ZXIoU3ltYm9sICVpbiUgZ2VuZV9saXN0KSAlPiUgIyBFbnN1cmUgb25seSBnZW5lcyBpbiBnZW5lX2xpc3QgYXJlIGtlcHQKICAgIGRwbHlyOjptdXRhdGUoZHBseXI6OmFjcm9zcygtU3ltYm9sLCBhcy5udW1lcmljKSkKCiAgIyBPcHRpb25hbGx5IHJlbW92ZSBnZW5lcyB0aGF0IGFyZSBOQSBhY3Jvc3MgYWxsIGNvbnRyYXN0cwogIGlmIChyZW1vdmVfbmFfZ2VuZXMpIHsKICAgIGRhdGFfd2lkZSA8LSBkYXRhX3dpZGUgJT4lCiAgICAgIGRwbHlyOjpmaWx0ZXIocm93U3Vtcyhpcy5uYShkcGx5cjo6c2VsZWN0KC4sIC1TeW1ib2wpKSkgPCBuY29sKGRhdGFfd2lkZSkgLSAxKQogIH0KCiAgIyBDcmVhdGUgYSBtYXRyaXggZm9yIGhlYXRtYXAgcGxvdHRpbmcKICBtYXQgPC0gYXMubWF0cml4KGRhdGFfd2lkZSAlPiUgZHBseXI6OnNlbGVjdCgtU3ltYm9sKSkKICByb3duYW1lcyhtYXQpIDwtIGRhdGFfd2lkZSRTeW1ib2wKICAKICAjIENoZWNrIGZvciBOQSwgTmFOLCBvciBJbmYgdmFsdWVzIGluIHRoZSBtYXRyaXggYW5kIHJlbW92ZSBhbnkgcm93cyBvciBjb2x1bW5zIHRoYXQgY29udGFpbiB0aGVtCiAgbWF0IDwtIG1hdFtjb21wbGV0ZS5jYXNlcyhtYXQpLCBdICAjIFJlbW92ZSByb3dzIHdpdGggTkEvTmFOL0luZiB2YWx1ZXMKICBtYXQgPC0gbWF0WywgY29sU3Vtcyhpcy5uYShtYXQpKSA9PSAwXSAgIyBSZW1vdmUgY29sdW1ucyB3aXRoIE5BL05hTi9JbmYgdmFsdWVzCiAgCiAgIyBJZiBhZnRlciByZW1vdmluZyBOQSByb3dzL2NvbHVtbnMgdGhlIG1hdHJpeCBiZWNvbWVzIGVtcHR5LCByZXR1cm4gYW4gaW5mb3JtYXRpdmUgZXJyb3IKICBpZiAobnJvdyhtYXQpID09IDAgfHwgbmNvbChtYXQpID09IDApIHsKICAgIHN0b3AoIlRoZSBtYXRyaXggaXMgZW1wdHkgYWZ0ZXIgcmVtb3Zpbmcgcm93cy9jb2x1bW5zIHdpdGggTkEvTmFOL0luZiB2YWx1ZXMuIE5vIHZhbGlkIGRhdGEgdG8gcGxvdC4iKQogIH0KICAKICAjIERldGVybWluZSB0aGUgbGltaXRzIGZvciB0aGUgc2NhbGUgdG8gYmUgc3ltbWV0cmljIGFyb3VuZCB6ZXJvCiAgbWF4X3ZhbCA8LSBtYXgoYWJzKG1hdCksIG5hLnJtID0gVFJVRSkKICAKICAjIENyZWF0ZSB0aGUgaGVhdG1hcCB3aXRoIGRlbmRyb2dyYW1zCiAgcGhlYXRtYXA6OnBoZWF0bWFwKG1hdCwgCiAgICAgICAgICAgICAgICAgICAgIGNsdXN0ZXJfcm93cyA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICBjbHVzdGVyX2NvbHMgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgc2NhbGUgPSAibm9uZSIsIAogICAgICAgICAgICAgICAgICAgICBjb2xvciA9IGNvbG9yUmFtcFBhbGV0dGUoYygiYmx1ZSIsICJ3aGl0ZSIsICJyZWQiKSkoNTApLAogICAgICAgICAgICAgICAgICAgICBicmVha3MgPSBzZXEoLW1heF92YWwsIG1heF92YWwsIGxlbmd0aC5vdXQgPSA1MSksICMgU3ltbWV0cmljIGNvbG9yIHNjYWxlCiAgICAgICAgICAgICAgICAgICAgIGNlbGx3aWR0aCA9IGNvbHVtbl93aWR0aCAqIDEwLCAjIEFkanVzdCBjb2x1bW4gd2lkdGgKICAgICAgICAgICAgICAgICAgICAgc2hvd19yb3duYW1lcyA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgIHNob3dfY29sbmFtZXMgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICBtYWluID0gdGl0bGUpCn0KCnBsb3RfbG9nZm9sZF9jaGFuZ2VfaGVhdG1hcF9kZW5kcm9ncmFtKGRmX2xpc3RfbnVtZXJpYywgZ2VuZV9saXN0ID0gbWl0b2NhcnRhJFN5bWJvbCwgY29udHJhc3RfbGlzdCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZV9uYV9nZW5lcyA9IFRSVUUsIGNvbHVtbl93aWR0aCA9IDEpCgoKCmBgYAoKR2VuZSBkaWZmZXJlbnQgaGVhdG1hcHMKCmBgYHtyfQpnZW5lX2xpc3QgPC0gbWl0by5nZW5lcwojZ2VuZV9saXN0IDwtIGx5c29tZSRgR2VuZSBuYW1lYApjb250cmFzdF9saXN0IDwtIGMoIlNOQ0EtQTUzVCIsICJHQkEtS08iLCAiUElOSzEtS08iLCAiUFJLTi1LTyIsICJJR1NGOUItS08iLCJJTlBQNUYtS08iLCJTSDNHTDItS08iLCJJUDZLMi1LTyIpCnAxIDwtIHBsb3RfbG9nZm9sZF9jaGFuZ2VfaGVhdG1hcF9kZW5kcm9ncmFtKGRmX2xpc3RfbnVtZXJpYywgZ2VuZV9saXN0LCBjb250cmFzdF9saXN0LCByZW1vdmVfbmFfZ2VuZXMgPSBUUlVFLCBjb2x1bW5fd2lkdGggPSAxLCB0aXRsZSA9ICJMb2cgRm9sZCBDaGFuZ2UgTWl0b2NhcnRhIEdlbmVzIikKcHJpbnQocDEpCgoKY29udHJhc3RfbGlzdCA8LSBjKCJTTkNBLUE1M1QiLCAiR0JBLUtPIiwgIlBJTksxLUtPIiwgIlBSS04tS08iKQpwMiA8LSBwbG90X2xvZ2ZvbGRfY2hhbmdlX2hlYXRtYXBfZGVuZHJvZ3JhbShkZl9saXN0X251bWVyaWMsIGdlbmVfbGlzdCwgY29udHJhc3RfbGlzdCwgcmVtb3ZlX25hX2dlbmVzID0gVFJVRSwgY29sdW1uX3dpZHRoID0gMSwgdGl0bGUgPSAiTG9nIEZvbGQgQ2hhbmdlIE1pdG9jYXJ0YSBHZW5lcyIpCnByaW50KHAyKQoKY29udHJhc3RfbGlzdCA8LSBjKCJJR1NGOUItS08iLCJJTlBQNUYtS08iLCJTSDNHTDItS08iLCJJUDZLMi1LTyIpCnAzIDwtcGxvdF9sb2dmb2xkX2NoYW5nZV9oZWF0bWFwX2RlbmRyb2dyYW0oZGZfbGlzdF9udW1lcmljLCBnZW5lX2xpc3QsIGNvbnRyYXN0X2xpc3QsIHJlbW92ZV9uYV9nZW5lcyA9IFRSVUUsIGNvbHVtbl93aWR0aCA9IDEsIHRpdGxlID0gIkxvZyBGb2xkIENoYW5nZSBNaXRvY2FydGEgR2VuZXMiKQpwcmludChwMykKCmNvbnRyYXN0X2xpc3QgPC0gYygiU05DQS1BNTNUIiwgIkdCQS1LTyIsICJQSU5LMS1LTyIsICJQUktOLUtPIiwiSU5QUDVGLUtPIiwiU0gzR0wyLUtPIiwiSVA2SzItS08iKQpwNCA8LSBwbG90X2xvZ2ZvbGRfY2hhbmdlX2hlYXRtYXBfZGVuZHJvZ3JhbShkZl9saXN0X251bWVyaWMsIGdlbmVfbGlzdCwgY29udHJhc3RfbGlzdCwgcmVtb3ZlX25hX2dlbmVzID0gVFJVRSwgY29sdW1uX3dpZHRoID0gMSwgdGl0bGUgPSAiTG9nIEZvbGQgQ2hhbmdlIE1pdG9jYXJ0YSBHZW5lcyIpCnByaW50KHA0KQoKCmNvbnRyYXN0X2xpc3QgPC0gYygiU05DQS1BNTNUIiwgIkdCQS1LTyIsICJQSU5LMS1LTyIsICJQUktOLUtPIiwgIklHU0Y5Qi1LTyIsIklOUFA1Ri1LTyIsIlNIM0dMMi1LTyIsIklQNksyLUtPIikKZ2VuZV9saXN0IDwtIG1pdG8uZ2VuZXNbMToxMDBdCnAxLjEgPC0gcGxvdF9sb2dmb2xkX2NoYW5nZV9oZWF0bWFwX2RlbmRyb2dyYW0oZGZfbGlzdF9udW1lcmljLCBnZW5lX2xpc3QsIGNvbnRyYXN0X2xpc3QsIHJlbW92ZV9uYV9nZW5lcyA9IFRSVUUsIGNvbHVtbl93aWR0aCA9IDEsIHRpdGxlID0gIkxvZyBGb2xkIENoYW5nZSBNaXRvY2FydGEgR2VuZXMgMS0xMDAiKQpwMS4xIAoKCmNvbnRyYXN0X2xpc3QgPC0gYygiU05DQS1BNTNUIiwgIkdCQS1LTyIsICJQSU5LMS1LTyIsICJQUktOLUtPIiwgIklHU0Y5Qi1LTyIsIklOUFA1Ri1LTyIsIlNIM0dMMi1LTyIsIklQNksyLUtPIikKZ2VuZV9saXN0IDwtIG1pdG8uZ2VuZXNbMTAxOjIwMF0KcDEuMiA8LSBwbG90X2xvZ2ZvbGRfY2hhbmdlX2hlYXRtYXBfZGVuZHJvZ3JhbShkZl9saXN0X251bWVyaWMsIGdlbmVfbGlzdCwgY29udHJhc3RfbGlzdCwgcmVtb3ZlX25hX2dlbmVzID0gVFJVRSwgY29sdW1uX3dpZHRoID0gMSwgdGl0bGUgPSAiTG9nIEZvbGQgQ2hhbmdlIE1pdG9jYXJ0YSBHZW5lcyAxMDEtMjAwIikKcDEuMgoKY29udHJhc3RfbGlzdCA8LSBjKCJTTkNBLUE1M1QiLCAiR0JBLUtPIiwgIlBJTksxLUtPIiwgIlBSS04tS08iLCAiSUdTRjlCLUtPIiwiSU5QUDVGLUtPIiwiU0gzR0wyLUtPIiwiSVA2SzItS08iKQpnZW5lX2xpc3QgPC0gbWl0by5nZW5lc1syMDE6MzAwXQpwMS4zIDwtIHBsb3RfbG9nZm9sZF9jaGFuZ2VfaGVhdG1hcF9kZW5kcm9ncmFtKGRmX2xpc3RfbnVtZXJpYywgZ2VuZV9saXN0LCBjb250cmFzdF9saXN0LCByZW1vdmVfbmFfZ2VuZXMgPSBUUlVFLCBjb2x1bW5fd2lkdGggPSAxLCB0aXRsZSA9ICJMb2cgRm9sZCBDaGFuZ2UgTWl0b2NhcnRhIEdlbmVzIDIwMS0zMDAiKQpwMS4zCgpjb250cmFzdF9saXN0IDwtIGMoIlNOQ0EtQTUzVCIsICJHQkEtS08iLCAiUElOSzEtS08iLCAiUFJLTi1LTyIsICJJR1NGOUItS08iLCJJTlBQNUYtS08iLCJTSDNHTDItS08iLCJJUDZLMi1LTyIpCmdlbmVfbGlzdCA8LSBtaXRvLmdlbmVzWzMwMTo0MDBdCnAxLjQgPC0gcGxvdF9sb2dmb2xkX2NoYW5nZV9oZWF0bWFwX2RlbmRyb2dyYW0oZGZfbGlzdF9udW1lcmljLCBnZW5lX2xpc3QsIGNvbnRyYXN0X2xpc3QsIHJlbW92ZV9uYV9nZW5lcyA9IFRSVUUsIGNvbHVtbl93aWR0aCA9IDEsIHRpdGxlID0gIkxvZyBGb2xkIENoYW5nZSBNaXRvY2FydGEgR2VuZXMgMzAxLTQwMCIpCnAxLjQKCmNvbnRyYXN0X2xpc3QgPC0gYygiU05DQS1BNTNUIiwgIkdCQS1LTyIsICJQSU5LMS1LTyIsICJQUktOLUtPIiwgIklHU0Y5Qi1LTyIsIklOUFA1Ri1LTyIsIlNIM0dMMi1LTyIsIklQNksyLUtPIikKZ2VuZV9saXN0IDwtIG1pdG8uZ2VuZXNbNDAxOjYwMF0KcDEuNSA8LSBwbG90X2xvZ2ZvbGRfY2hhbmdlX2hlYXRtYXBfZGVuZHJvZ3JhbShkZl9saXN0X251bWVyaWMsIGdlbmVfbGlzdCwgY29udHJhc3RfbGlzdCwgcmVtb3ZlX25hX2dlbmVzID0gVFJVRSwgY29sdW1uX3dpZHRoID0gMSwgdGl0bGUgPSAiTG9nIEZvbGQgQ2hhbmdlIE1pdG9jYXJ0YSBHZW5lcyA0MDEtNjAwIikKcDEuNQoKY29udHJhc3RfbGlzdCA8LSBjKCJTTkNBLUE1M1QiLCAiR0JBLUtPIiwgIlBJTksxLUtPIiwgIlBSS04tS08iLCAiSUdTRjlCLUtPIiwiSU5QUDVGLUtPIiwiU0gzR0wyLUtPIiwiSVA2SzItS08iKQpnZW5lX2xpc3QgPC0gbWl0by5nZW5lc1s2MDE6ODAwXQpwMS42IDwtIHBsb3RfbG9nZm9sZF9jaGFuZ2VfaGVhdG1hcF9kZW5kcm9ncmFtKGRmX2xpc3RfbnVtZXJpYywgZ2VuZV9saXN0LCBjb250cmFzdF9saXN0LCByZW1vdmVfbmFfZ2VuZXMgPSBUUlVFLCBjb2x1bW5fd2lkdGggPSAxLCB0aXRsZSA9ICJMb2cgRm9sZCBDaGFuZ2UgTWl0b2NhcnRhIEdlbmVzIDYwMS04MDAiKQpwMS42Cgpjb250cmFzdF9saXN0IDwtIGMoIlNOQ0EtQTUzVCIsICJHQkEtS08iLCAiUElOSzEtS08iLCAiUFJLTi1LTyIsICJJR1NGOUItS08iLCJJTlBQNUYtS08iLCJTSDNHTDItS08iLCJJUDZLMi1LTyIpCmdlbmVfbGlzdCA8LSBtaXRvLmdlbmVzWzgwMToxMTM2XQpwMS43IDwtIHBsb3RfbG9nZm9sZF9jaGFuZ2VfaGVhdG1hcF9kZW5kcm9ncmFtKGRmX2xpc3RfbnVtZXJpYywgZ2VuZV9saXN0LCBjb250cmFzdF9saXN0LCByZW1vdmVfbmFfZ2VuZXMgPSBUUlVFLCBjb2x1bW5fd2lkdGggPSAxLCB0aXRsZSA9ICJMb2cgRm9sZCBDaGFuZ2UgTWl0b2NhcnRhIEdlbmVzIDgwMS0xMTM2IikKcDEuNwoKCgpgYGAKClNhdmUgbWl0b2NoYXJ0YSBwbG90cwoKYGBge3J9CnBkZigiL1VzZXJzL3JoYWxlbmF0aG9tYXMvRG93bmxvYWRzL01vdmVfRGF0YS9EYXJrR2Vub21lUmVzdWx0L29taWNzL0hNX01pdG9jaGFydGFfTG9nMkZDX2RlbmRyb2dyYW0ucGRmIikKcDEKcDEuMQpwMS4yCnAxLjMKcDEuNApwMS41CnAxLjYKcDEuNwpwMgpwMwpwNApkZXYub2ZmKCkKCmBgYAoKUmVhZCBpbiBhbm90aGVyIGxpc3Qgb2YgZ2VuZXMKCmBgYHtyfQoKcGQuZ2VuZXMubGlzdCA8LSByZWFkX2V4Y2VsKCIvVXNlcnMvcmhhbGVuYXRob21hcy9Eb3dubG9hZHMvTW92ZV9EYXRhL0RhcmtHZW5vbWVSZXN1bHQvTGlzdCBvZiBnZW5lcyBmb3IgUk5Bc2VxIG9yIFByb3Rlb21pY3MvUEQgZ2VuZSBsaXN0Lnhsc3giLCBza2lwID0gMSkKaGVhZChwZC5nZW5lcy5saXN0KQpjb2xuYW1lcyhwZC5nZW5lcy5saXN0KSA8LSBjKCJTeW1ib2wiLCJBY2Nlc3Npb24iLCJEZXNjcmlwdGlvbiIsIlJlZiIsIlNwZWNpZXMiKQpoZWFkKHBkLmdlbmVzLmxpc3QpCnBkLmdlbmVzIDwtIHBkLmdlbmVzLmxpc3QkU3ltYm9sCgpgYGAKTG9vayBhdCB0aGUgZ2VuZSBsaXN0IGZvciBQRAoKYGBge3J9CgpnZW5lX2xpc3QgPC0gcGQuZ2VuZXMKI2dlbmVfbGlzdCA8LSBseXNvbWUkYEdlbmUgbmFtZWAKY29udHJhc3RfbGlzdCA8LSBjKCJTTkNBLUE1M1QiLCAiR0JBLUtPIiwgIlBJTksxLUtPIiwgIlBSS04tS08iLCAiSUdTRjlCLUtPIiwiSU5QUDVGLUtPIiwiU0gzR0wyLUtPIiwiSVA2SzItS08iKQpwMSA8LSBwbG90X2xvZ2ZvbGRfY2hhbmdlX2hlYXRtYXBfZGVuZHJvZ3JhbShkZl9saXN0X251bWVyaWMsIGdlbmVfbGlzdCwgY29udHJhc3RfbGlzdCwgcmVtb3ZlX25hX2dlbmVzID0gVFJVRSwgY29sdW1uX3dpZHRoID0gMSwgdGl0bGUgPSAiTG9nIEZvbGQgQ2hhbmdlIFBEIEdlbmVzIikKcHJpbnQocDEpCgoKY29udHJhc3RfbGlzdCA8LSBjKCJTTkNBLUE1M1QiLCAiR0JBLUtPIiwgIlBJTksxLUtPIiwgIlBSS04tS08iKQpwMiA8LSBwbG90X2xvZ2ZvbGRfY2hhbmdlX2hlYXRtYXBfZGVuZHJvZ3JhbShkZl9saXN0X251bWVyaWMsIGdlbmVfbGlzdCwgY29udHJhc3RfbGlzdCwgcmVtb3ZlX25hX2dlbmVzID0gVFJVRSwgY29sdW1uX3dpZHRoID0gMSwgdGl0bGUgPSAiTG9nIEZvbGQgQ2hhbmdlIFBEIEdlbmVzIikKcHJpbnQocDIpCgpjb250cmFzdF9saXN0IDwtIGMoIklHU0Y5Qi1LTyIsIklOUFA1Ri1LTyIsIlNIM0dMMi1LTyIsIklQNksyLUtPIikKcDMgPC1wbG90X2xvZ2ZvbGRfY2hhbmdlX2hlYXRtYXBfZGVuZHJvZ3JhbShkZl9saXN0X251bWVyaWMsIGdlbmVfbGlzdCwgY29udHJhc3RfbGlzdCwgcmVtb3ZlX25hX2dlbmVzID0gVFJVRSwgY29sdW1uX3dpZHRoID0gMSwgdGl0bGUgPSAiTG9nIEZvbGQgQ2hhbmdlIFBEIEdlbmVzIikKcHJpbnQocDMpCgpjb250cmFzdF9saXN0IDwtIGMoIlNOQ0EtQTUzVCIsICJHQkEtS08iLCAiUElOSzEtS08iLCAiUFJLTi1LTyIsIklOUFA1Ri1LTyIsIlNIM0dMMi1LTyIsIklQNksyLUtPIikKcDQgPC0gcGxvdF9sb2dmb2xkX2NoYW5nZV9oZWF0bWFwX2RlbmRyb2dyYW0oZGZfbGlzdF9udW1lcmljLCBnZW5lX2xpc3QsIGNvbnRyYXN0X2xpc3QsIHJlbW92ZV9uYV9nZW5lcyA9IFRSVUUsIGNvbHVtbl93aWR0aCA9IDEsIHRpdGxlID0gIkxvZyBGb2xkIENoYW5nZSBQRCBHZW5lcyIpCnByaW50KHA0KQoKCmNvbnRyYXN0X2xpc3QgPC0gYygiU05DQS1BNTNUIiwgIkdCQS1LTyIsICJQSU5LMS1LTyIsICJQUktOLUtPIiwgIklHU0Y5Qi1LTyIsIklOUFA1Ri1LTyIsIlNIM0dMMi1LTyIsIklQNksyLUtPIikKZ2VuZV9saXN0IDwtIHBkLmdlbmVzWzE6NTBdCnAxLjEgPC0gcGxvdF9sb2dmb2xkX2NoYW5nZV9oZWF0bWFwX2RlbmRyb2dyYW0oZGZfbGlzdF9udW1lcmljLCBnZW5lX2xpc3QsIGNvbnRyYXN0X2xpc3QsIHJlbW92ZV9uYV9nZW5lcyA9IFRSVUUsIGNvbHVtbl93aWR0aCA9IDEsIHRpdGxlID0gIkxvZyBGb2xkIENoYW5nZSBQRCBHZW5lcyAxLTUwIikKcDEuMSAKCgpjb250cmFzdF9saXN0IDwtIGMoIlNOQ0EtQTUzVCIsICJHQkEtS08iLCAiUElOSzEtS08iLCAiUFJLTi1LTyIsICJJR1NGOUItS08iLCJJTlBQNUYtS08iLCJTSDNHTDItS08iLCJJUDZLMi1LTyIpCmdlbmVfbGlzdCA8LSBwZC5nZW5lc1s1MDoxMDBdCnAxLjIgPC0gcGxvdF9sb2dmb2xkX2NoYW5nZV9oZWF0bWFwX2RlbmRyb2dyYW0oZGZfbGlzdF9udW1lcmljLCBnZW5lX2xpc3QsIGNvbnRyYXN0X2xpc3QsIHJlbW92ZV9uYV9nZW5lcyA9IFRSVUUsIGNvbHVtbl93aWR0aCA9IDEsIHRpdGxlID0gIkxvZyBGb2xkIENoYW5nZSBQRCBHZW5lcyA1MC0xMDAiKQpwMS4yCgpjb250cmFzdF9saXN0IDwtIGMoIlNOQ0EtQTUzVCIsICJHQkEtS08iLCAiUElOSzEtS08iLCAiUFJLTi1LTyIsICJJR1NGOUItS08iLCJJTlBQNUYtS08iLCJTSDNHTDItS08iLCJJUDZLMi1LTyIpCmdlbmVfbGlzdCA8LSBwZC5nZW5lc1sxMDA6MTUwXQpwMS4zIDwtIHBsb3RfbG9nZm9sZF9jaGFuZ2VfaGVhdG1hcF9kZW5kcm9ncmFtKGRmX2xpc3RfbnVtZXJpYywgZ2VuZV9saXN0LCBjb250cmFzdF9saXN0LCByZW1vdmVfbmFfZ2VuZXMgPSBUUlVFLCBjb2x1bW5fd2lkdGggPSAxLCB0aXRsZSA9ICJMb2cgRm9sZCBDaGFuZ2UgUEQgR2VuZXMgMTAwLTE1MCIpCnAxLjMKCmNvbnRyYXN0X2xpc3QgPC0gYygiU05DQS1BNTNUIiwgIkdCQS1LTyIsICJQSU5LMS1LTyIsICJQUktOLUtPIiwgIklHU0Y5Qi1LTyIsIklOUFA1Ri1LTyIsIlNIM0dMMi1LTyIsIklQNksyLUtPIikKZ2VuZV9saXN0IDwtIHBkLmdlbmVzWzE1MDoyMDBdCnAxLjQgPC0gcGxvdF9sb2dmb2xkX2NoYW5nZV9oZWF0bWFwX2RlbmRyb2dyYW0oZGZfbGlzdF9udW1lcmljLCBnZW5lX2xpc3QsIGNvbnRyYXN0X2xpc3QsIHJlbW92ZV9uYV9nZW5lcyA9IFRSVUUsIGNvbHVtbl93aWR0aCA9IDEsIHRpdGxlID0gIkxvZyBGb2xkIENoYW5nZSBQRCBHZW5lcyAxNTAtMjAwIikKcDEuNAoKY29udHJhc3RfbGlzdCA8LSBjKCJTTkNBLUE1M1QiLCAiR0JBLUtPIiwgIlBJTksxLUtPIiwgIlBSS04tS08iLCAiSUdTRjlCLUtPIiwiSU5QUDVGLUtPIiwiU0gzR0wyLUtPIiwiSVA2SzItS08iKQpnZW5lX2xpc3QgPC0gcGQuZ2VuZXNbMjAwOjI1MF0KcDEuNSA8LSBwbG90X2xvZ2ZvbGRfY2hhbmdlX2hlYXRtYXBfZGVuZHJvZ3JhbShkZl9saXN0X251bWVyaWMsIGdlbmVfbGlzdCwgY29udHJhc3RfbGlzdCwgcmVtb3ZlX25hX2dlbmVzID0gVFJVRSwgY29sdW1uX3dpZHRoID0gMSwgdGl0bGUgPSAiTG9nIEZvbGQgQ2hhbmdlIFBEIEdlbmVzIDIwMC0yNTAiKQpwMS41Cgpjb250cmFzdF9saXN0IDwtIGMoIlNOQ0EtQTUzVCIsICJHQkEtS08iLCAiUElOSzEtS08iLCAiUFJLTi1LTyIsICJJR1NGOUItS08iLCJJTlBQNUYtS08iLCJTSDNHTDItS08iLCJJUDZLMi1LTyIpCmdlbmVfbGlzdCA8LSBwZC5nZW5lc1syNTA6MzAwXQpwMS42IDwtIHBsb3RfbG9nZm9sZF9jaGFuZ2VfaGVhdG1hcF9kZW5kcm9ncmFtKGRmX2xpc3RfbnVtZXJpYywgZ2VuZV9saXN0LCBjb250cmFzdF9saXN0LCByZW1vdmVfbmFfZ2VuZXMgPSBUUlVFLCBjb2x1bW5fd2lkdGggPSAxLCB0aXRsZSA9ICJMb2cgRm9sZCBDaGFuZ2UgUEQgR2VuZXMgMjUwLTMwMCIpCnAxLjYKCmNvbnRyYXN0X2xpc3QgPC0gYygiU05DQS1BNTNUIiwgIkdCQS1LTyIsICJQSU5LMS1LTyIsICJQUktOLUtPIiwgIklHU0Y5Qi1LTyIsIklOUFA1Ri1LTyIsIlNIM0dMMi1LTyIsIklQNksyLUtPIikKZ2VuZV9saXN0IDwtIHBkLmdlbmVzWzMwMDozMzBdCnAxLjcgPC0gcGxvdF9sb2dmb2xkX2NoYW5nZV9oZWF0bWFwX2RlbmRyb2dyYW0oZGZfbGlzdF9udW1lcmljLCBnZW5lX2xpc3QsIGNvbnRyYXN0X2xpc3QsIHJlbW92ZV9uYV9nZW5lcyA9IFRSVUUsIGNvbHVtbl93aWR0aCA9IDEsIHRpdGxlID0gIkxvZyBGb2xkIENoYW5nZSBQRCBHZW5lcyAzMDAtMzMwIikKcDEuNwoKCmBgYAoKYGBge3J9CnBkZigiL1VzZXJzL3JoYWxlbmF0aG9tYXMvRG93bmxvYWRzL01vdmVfRGF0YS9EYXJrR2Vub21lUmVzdWx0L29taWNzL0hNX1BEX2dlbmVzX0xvZzJGQ19kZW5kcm9ncmFtLnBkZiIpCnAxCnAxLjEKcDEuMgpwMS4zCnAxLjQKcDEuNQpwMS42CnAxLjcKcDIKcDMKcDQKZGV2Lm9mZigpCgpgYGAKClJlYWQgc3luYXBzZSBsaXN0IAoKYGBge3J9CnN5bmFwc2UuZ2VuZXMubGlzdCA8LSByZWFkX2V4Y2VsKCIvVXNlcnMvcmhhbGVuYXRob21hcy9Eb3dubG9hZHMvTW92ZV9EYXRhL0RhcmtHZW5vbWVSZXN1bHQvTGlzdCBvZiBnZW5lcyBmb3IgUk5Bc2VxIG9yIFByb3Rlb21pY3MvU1lOQVBTRV9SRURVQ0VEX0dFTkVfTElTVC54bHN4IiwgY29sX25hbWVzID0gRkFMU0UpCmhlYWQoc3luYXBzZS5nZW5lcy5saXN0KQpjb2xuYW1lcyhzeW5hcHNlLmdlbmVzLmxpc3QpIDwtIGMoIlN5bWJvbCIpCmhlYWQoc3luYXBzZS5nZW5lcy5saXN0KQpzeW5hcHNlLmdlbmVzIDwtIHN5bmFwc2UuZ2VuZXMubGlzdCRTeW1ib2wKYGBgCgpgYGB7cn0KZ2VuZV9saXN0IDwtIHN5bmFwc2UuZ2VuZXMKI2dlbmVfbGlzdCA8LSBseXNvbWUkYEdlbmUgbmFtZWAKY29udHJhc3RfbGlzdCA8LSBjKCJTTkNBLUE1M1QiLCAiR0JBLUtPIiwgIlBJTksxLUtPIiwgIlBSS04tS08iLCAiSUdTRjlCLUtPIiwiSU5QUDVGLUtPIiwiU0gzR0wyLUtPIiwiSVA2SzItS08iKQpwMSA8LSBwbG90X2xvZ2ZvbGRfY2hhbmdlX2hlYXRtYXBfZGVuZHJvZ3JhbShkZl9saXN0X251bWVyaWMsIGdlbmVfbGlzdCwgY29udHJhc3RfbGlzdCwgcmVtb3ZlX25hX2dlbmVzID0gVFJVRSwgY29sdW1uX3dpZHRoID0gMSwgdGl0bGUgPSAiTG9nIEZvbGQgQ2hhbmdlIFN5bmFwc2UgR2VuZXMiKQpwcmludChwMSkKCgpjb250cmFzdF9saXN0IDwtIGMoIlNOQ0EtQTUzVCIsICJHQkEtS08iLCAiUElOSzEtS08iLCAiUFJLTi1LTyIpCnAyIDwtIHBsb3RfbG9nZm9sZF9jaGFuZ2VfaGVhdG1hcF9kZW5kcm9ncmFtKGRmX2xpc3RfbnVtZXJpYywgZ2VuZV9saXN0LCBjb250cmFzdF9saXN0LCByZW1vdmVfbmFfZ2VuZXMgPSBUUlVFLCBjb2x1bW5fd2lkdGggPSAxLCB0aXRsZSA9ICJMb2cgRm9sZCBDaGFuZ2UgU3luYXBzZSBHZW5lcyIpCnByaW50KHAyKQoKY29udHJhc3RfbGlzdCA8LSBjKCJJR1NGOUItS08iLCJJTlBQNUYtS08iLCJTSDNHTDItS08iLCJJUDZLMi1LTyIpCnAzIDwtcGxvdF9sb2dmb2xkX2NoYW5nZV9oZWF0bWFwX2RlbmRyb2dyYW0oZGZfbGlzdF9udW1lcmljLCBnZW5lX2xpc3QsIGNvbnRyYXN0X2xpc3QsIHJlbW92ZV9uYV9nZW5lcyA9IFRSVUUsIGNvbHVtbl93aWR0aCA9IDEsIHRpdGxlID0gIkxvZyBGb2xkIENoYW5nZSBTeW5hcHNlIEdlbmVzIikKcHJpbnQocDMpCgpjb250cmFzdF9saXN0IDwtIGMoIlNOQ0EtQTUzVCIsICJHQkEtS08iLCAiUElOSzEtS08iLCAiUFJLTi1LTyIsIklOUFA1Ri1LTyIsIlNIM0dMMi1LTyIsIklQNksyLUtPIikKcDQgPC0gcGxvdF9sb2dmb2xkX2NoYW5nZV9oZWF0bWFwX2RlbmRyb2dyYW0oZGZfbGlzdF9udW1lcmljLCBnZW5lX2xpc3QsIGNvbnRyYXN0X2xpc3QsIHJlbW92ZV9uYV9nZW5lcyA9IFRSVUUsIGNvbHVtbl93aWR0aCA9IDEsIHRpdGxlID0gIkxvZyBGb2xkIENoYW5nZSBTeW5hcHNlIEdlbmVzIikKcHJpbnQocDQpCgoKY29udHJhc3RfbGlzdCA8LSBjKCJTTkNBLUE1M1QiLCAiR0JBLUtPIiwgIlBJTksxLUtPIiwgIlBSS04tS08iLCAiSUdTRjlCLUtPIiwiSU5QUDVGLUtPIiwiU0gzR0wyLUtPIiwiSVA2SzItS08iKQpnZW5lX2xpc3QgPC0gc3luYXBzZS5nZW5lc1sxOjEwMF0KcDEuMSA8LSBwbG90X2xvZ2ZvbGRfY2hhbmdlX2hlYXRtYXBfZGVuZHJvZ3JhbShkZl9saXN0X251bWVyaWMsIGdlbmVfbGlzdCwgY29udHJhc3RfbGlzdCwgcmVtb3ZlX25hX2dlbmVzID0gVFJVRSwgY29sdW1uX3dpZHRoID0gMSwgdGl0bGUgPSAiTG9nIEZvbGQgQ2hhbmdlIFN5bmFwc2UgR2VuZXMgMS0xMDAiKQpwMS4xIAoKCmNvbnRyYXN0X2xpc3QgPC0gYygiU05DQS1BNTNUIiwgIkdCQS1LTyIsICJQSU5LMS1LTyIsICJQUktOLUtPIiwgIklHU0Y5Qi1LTyIsIklOUFA1Ri1LTyIsIlNIM0dMMi1LTyIsIklQNksyLUtPIikKZ2VuZV9saXN0IDwtIHN5bmFwc2UuZ2VuZXNbMTAwOjIwMF0KcDEuMiA8LSBwbG90X2xvZ2ZvbGRfY2hhbmdlX2hlYXRtYXBfZGVuZHJvZ3JhbShkZl9saXN0X251bWVyaWMsIGdlbmVfbGlzdCwgY29udHJhc3RfbGlzdCwgcmVtb3ZlX25hX2dlbmVzID0gVFJVRSwgY29sdW1uX3dpZHRoID0gMSwgdGl0bGUgPSAiTG9nIEZvbGQgQ2hhbmdlIFN5bmFwc2UgR2VuZXMgMTAwLTIwMCIpCnAxLjIKCmNvbnRyYXN0X2xpc3QgPC0gYygiU05DQS1BNTNUIiwgIkdCQS1LTyIsICJQSU5LMS1LTyIsICJQUktOLUtPIiwgIklHU0Y5Qi1LTyIsIklOUFA1Ri1LTyIsIlNIM0dMMi1LTyIsIklQNksyLUtPIikKZ2VuZV9saXN0IDwtIHN5bmFwc2UuZ2VuZXNbMjAwOjMwMF0KcDEuMyA8LXBsb3RfbG9nZm9sZF9jaGFuZ2VfaGVhdG1hcF9kZW5kcm9ncmFtKGRmX2xpc3RfbnVtZXJpYywgZ2VuZV9saXN0LCBjb250cmFzdF9saXN0LCByZW1vdmVfbmFfZ2VuZXMgPSBUUlVFLCBjb2x1bW5fd2lkdGggPSAxLCB0aXRsZSA9ICJMb2cgRm9sZCBDaGFuZ2UgU3luYXBzZSBHZW5lcyAyMDAtMzAwIikKcDEuMwoKY29udHJhc3RfbGlzdCA8LSBjKCJTTkNBLUE1M1QiLCAiR0JBLUtPIiwgIlBJTksxLUtPIiwgIlBSS04tS08iLCAiSUdTRjlCLUtPIiwiSU5QUDVGLUtPIiwiU0gzR0wyLUtPIiwiSVA2SzItS08iKQpnZW5lX2xpc3QgPC0gc3luYXBzZS5nZW5lc1szMDA6NDAwXQpwMS40IDwtIHBsb3RfbG9nZm9sZF9jaGFuZ2VfaGVhdG1hcF9kZW5kcm9ncmFtKGRmX2xpc3RfbnVtZXJpYywgZ2VuZV9saXN0LCBjb250cmFzdF9saXN0LCByZW1vdmVfbmFfZ2VuZXMgPSBUUlVFLCBjb2x1bW5fd2lkdGggPSAxLCB0aXRsZSA9ICJMb2cgRm9sZCBDaGFuZ2UgU3luYXBzZSBHZW5lcyAzMDAtNDAwIikKcDEuNAoKY29udHJhc3RfbGlzdCA8LSBjKCJTTkNBLUE1M1QiLCAiR0JBLUtPIiwgIlBJTksxLUtPIiwgIlBSS04tS08iLCAiSUdTRjlCLUtPIiwiSU5QUDVGLUtPIiwiU0gzR0wyLUtPIiwiSVA2SzItS08iKQpnZW5lX2xpc3QgPC0gc3luYXBzZS5nZW5lc1s0MDA6NTAwXQpwMS41IDwtIHBsb3RfbG9nZm9sZF9jaGFuZ2VfaGVhdG1hcF9kZW5kcm9ncmFtKGRmX2xpc3RfbnVtZXJpYywgZ2VuZV9saXN0LCBjb250cmFzdF9saXN0LCByZW1vdmVfbmFfZ2VuZXMgPSBUUlVFLCBjb2x1bW5fd2lkdGggPSAxLCB0aXRsZSA9ICJMb2cgRm9sZCBDaGFuZ2UgU3luYXBzZSBHZW5lcyA0MDAtNTAwIikKcDEuNQoKY29udHJhc3RfbGlzdCA8LSBjKCJTTkNBLUE1M1QiLCAiR0JBLUtPIiwgIlBJTksxLUtPIiwgIlBSS04tS08iLCAiSUdTRjlCLUtPIiwiSU5QUDVGLUtPIiwiU0gzR0wyLUtPIiwiSVA2SzItS08iKQpnZW5lX2xpc3QgPC0gc3luYXBzZS5nZW5lc1s1MDA6NTk0XQpwMS42IDwtIHBsb3RfbG9nZm9sZF9jaGFuZ2VfaGVhdG1hcF9kZW5kcm9ncmFtKGRmX2xpc3RfbnVtZXJpYywgZ2VuZV9saXN0LCBjb250cmFzdF9saXN0LCByZW1vdmVfbmFfZ2VuZXMgPSBUUlVFLCBjb2x1bW5fd2lkdGggPSAxLCB0aXRsZSA9ICJMb2cgRm9sZCBDaGFuZ2UgU3luYXBzZSBHZW5lcyA1MDAtNTk0IikKcDEuNgoKYGBgCgpzYXZlIHRoZSBzeW5hcHRpYyBnZW5lIGxpc3QKCmBgYHtyfQpwZGYoIi9Vc2Vycy9yaGFsZW5hdGhvbWFzL0Rvd25sb2Fkcy9Nb3ZlX0RhdGEvRGFya0dlbm9tZVJlc3VsdC9vbWljcy9ITV9TeW5wYXRpY19nZW5lc19Mb2cyRkNfZGVuZHJvZ3JhbS5wZGYiKQpwMQpwMS4xCnAxLjIKcDEuMwpwMS40CnAxLjUKcDEuNgpwMgpwMwpwNApkZXYub2ZmKCkKYGBgCgoKYGBge3J9CgpicmFpbkQuZ2VuZXMubGlzdCA8LSByZWFkLmNzdigiL1VzZXJzL3JoYWxlbmF0aG9tYXMvRG93bmxvYWRzL01vdmVfRGF0YS9EYXJrR2Vub21lUmVzdWx0L0xpc3Qgb2YgZ2VuZXMgZm9yIFJOQXNlcSBvciBQcm90ZW9taWNzL0JyYWluIERpc2Vhc2VzIC0gQnJhaW5CYXNlIC0gQ05DQi1OR0RDLmNzdiIpCmhlYWQoYnJhaW5ELmdlbmVzLmxpc3QpCiMgY2Fubm90IHVzZSAtIGdlbmUuc3ltYm9sIG5lZWRzIHdvdWxkIG5lZWQgdG8gYmUgY29udmVydGVkIHRvIFN5bWJvbCBhbmQgdGhlIGxpc3QgaXMgbG9uZyBzbyBpdCB3b3VsZG4ndCBiZSB2ZXJ5IHVzZWZ1bAojIHRyeSB3aXRoIGFsbCBhbmQgdGhlbiBmaWx0ZXIgZGlmZmVyZW50bHkKCgoKCmBgYApHV0FTIFBECgpgYGB7cn0KZ3dhcy5nZW5lcyA8LSByZWFkLmNzdigiL1VzZXJzL3JoYWxlbmF0aG9tYXMvRG93bmxvYWRzL01vdmVfRGF0YS9EYXJrR2Vub21lUmVzdWx0L0xpc3Qgb2YgZ2VuZXMgZm9yIFJOQXNlcSBvciBQcm90ZW9taWNzL0FMTF9QRF9HV0FTX0dFTkVMSVNULmNzdiIpCmhlYWQoZ3dhcy5nZW5lcykKCgpgYGAKQWxsIGd3YXMgZ2VuZXMKCgpgYGB7cn0KZ2VuZV9saXN0IDwtIGd3YXMuZ2VuZXMkaGduY19zeW1ib2wKI2dlbmVfbGlzdCA8LSBseXNvbWUkYEdlbmUgbmFtZWAKY29udHJhc3RfbGlzdCA8LSBjKCJTTkNBLUE1M1QiLCAiR0JBLUtPIiwgIlBJTksxLUtPIiwgIlBSS04tS08iLCAiSUdTRjlCLUtPIiwiSU5QUDVGLUtPIiwiU0gzR0wyLUtPIiwiSVA2SzItS08iKQpwMSA8LSBwbG90X2xvZ2ZvbGRfY2hhbmdlX2hlYXRtYXBfZGVuZHJvZ3JhbShkZl9saXN0X251bWVyaWMsIGdlbmVfbGlzdCwgY29udHJhc3RfbGlzdCwgcmVtb3ZlX25hX2dlbmVzID0gVFJVRSwgY29sdW1uX3dpZHRoID0gMSwgdGl0bGUgPSAiTG9nIEZvbGQgQ2hhbmdlIEFsbCBHV0FTIEdlbmVzIikKcHJpbnQocDEpCgoKY29udHJhc3RfbGlzdCA8LSBjKCJTTkNBLUE1M1QiLCAiR0JBLUtPIiwgIlBJTksxLUtPIiwgIlBSS04tS08iKQpwMiA8LSBwbG90X2xvZ2ZvbGRfY2hhbmdlX2hlYXRtYXBfZGVuZHJvZ3JhbShkZl9saXN0X251bWVyaWMsIGdlbmVfbGlzdCwgY29udHJhc3RfbGlzdCwgcmVtb3ZlX25hX2dlbmVzID0gVFJVRSwgY29sdW1uX3dpZHRoID0gMSwgdGl0bGUgPSAiTG9nIEZvbGQgQ2hhbmdlIEFsbCBHV0FTIEdlbmVzIikKcHJpbnQocDIpCgpjb250cmFzdF9saXN0IDwtIGMoIklHU0Y5Qi1LTyIsIklOUFA1Ri1LTyIsIlNIM0dMMi1LTyIsIklQNksyLUtPIikKcDMgPC1wbG90X2xvZ2ZvbGRfY2hhbmdlX2hlYXRtYXBfZGVuZHJvZ3JhbShkZl9saXN0X251bWVyaWMsIGdlbmVfbGlzdCwgY29udHJhc3RfbGlzdCwgcmVtb3ZlX25hX2dlbmVzID0gVFJVRSwgY29sdW1uX3dpZHRoID0gMSwgdGl0bGUgPSAiTG9nIEZvbGQgQ2hhbmdlIEFsbCBHV0FTIEdlbmVzIikKcHJpbnQocDMpCgpjb250cmFzdF9saXN0IDwtIGMoIlNOQ0EtQTUzVCIsICJHQkEtS08iLCAiUElOSzEtS08iLCAiUFJLTi1LTyIsIklOUFA1Ri1LTyIsIlNIM0dMMi1LTyIsIklQNksyLUtPIikKcDQgPC0gcDQgPC0gcGxvdF9sb2dmb2xkX2NoYW5nZV9oZWF0bWFwX2RlbmRyb2dyYW0oZGZfbGlzdF9udW1lcmljLCBnZW5lX2xpc3QsIGNvbnRyYXN0X2xpc3QsIHJlbW92ZV9uYV9nZW5lcyA9IFRSVUUsIGNvbHVtbl93aWR0aCA9IDEsIHRpdGxlID0gIkxvZyBGb2xkIENoYW5nZSBBbGwgR1dBUyBHZW5lcyIpCnByaW50KHA0KQoKCmNvbnRyYXN0X2xpc3QgPC0gYygiU05DQS1BNTNUIiwgIkdCQS1LTyIsICJQSU5LMS1LTyIsICJQUktOLUtPIiwgIklHU0Y5Qi1LTyIsIklOUFA1Ri1LTyIsIlNIM0dMMi1LTyIsIklQNksyLUtPIikKCmdlbmVfbGlzdCA8LSBnd2FzLmdlbmVzICU+JQogIGZpbHRlcihkaXN0YW5jZV90b19jbG9zZXN0X3NucCA9PSAwKSAlPiUKICBwdWxsKGhnbmNfc3ltYm9sKQpwcmludChnZW5lX2xpc3QpCiAgCnAxLjEgPC0gcDQgPC0gcGxvdF9sb2dmb2xkX2NoYW5nZV9oZWF0bWFwX2RlbmRyb2dyYW0oZGZfbGlzdF9udW1lcmljLCBnZW5lX2xpc3QsIGNvbnRyYXN0X2xpc3QsIHJlbW92ZV9uYV9nZW5lcyA9IFRSVUUsIGNvbHVtbl93aWR0aCA9IDEsIHRpdGxlID0gIkxvZyBGb2xkIENoYW5nZSBHV0FTIEdlbmVzIHdpdGggZGlzdGFuY2UgPSAwIikKcDEuMSAKCgpnZW5lX2xpc3QgPC0gZ3dhcy5nZW5lcyAlPiUKICBmaWx0ZXIoZGlzdGFuY2VfdG9fY2xvc2VzdF9zbnAgPCAxMDAwMCAmIGRpc3RhbmNlX3RvX2Nsb3Nlc3Rfc25wID4gMCkgJT4lCiAgcHVsbChoZ25jX3N5bWJvbCkKcHJpbnQoZ2VuZV9saXN0KQoKCnByaW50KGdlbmVfbGlzdCkKcDEuMiA8LSBwbG90X2xvZ2ZvbGRfY2hhbmdlX2hlYXRtYXBfZGVuZHJvZ3JhbShkZl9saXN0X251bWVyaWMsIGdlbmVfbGlzdCwgY29udHJhc3RfbGlzdCwgcmVtb3ZlX25hX2dlbmVzID0gVFJVRSwgY29sdW1uX3dpZHRoID0gMSwgdGl0bGUgPSAiTG9nIEZvbGQgQ2hhbmdlIEdXQVMgR2VuZXMgd2l0aCBkaXN0YW5jZSA+IDAgYW5kIDwgMTAwMDAiKQpwMS4yCgpnZW5lX2xpc3QgPC0gZ3dhcy5nZW5lcyAlPiUKICBmaWx0ZXIoZGlzdGFuY2VfdG9fY2xvc2VzdF9zbnAgPiAxMDAwMCkgJT4lCiAgcHVsbChoZ25jX3N5bWJvbCkKcHJpbnQoZ2VuZV9saXN0KQoKcDEuMyA8LXBsb3RfbG9nZm9sZF9jaGFuZ2VfaGVhdG1hcF9kZW5kcm9ncmFtKGRmX2xpc3RfbnVtZXJpYywgZ2VuZV9saXN0LCBjb250cmFzdF9saXN0LCByZW1vdmVfbmFfZ2VuZXMgPSBUUlVFLCBjb2x1bW5fd2lkdGggPSAxLCB0aXRsZSA9ICJMb2cgRm9sZCBDaGFuZ2UgR1dBUyBHZW5lcyB3aXRoIGRpc3RhbmNlID4gMTAwMDAiKQpwMS4zCgoKCgpnZW5lX2xpc3QgPC0gZ3dhcy5nZW5lcyAlPiUKICBmaWx0ZXIoZGlzdGFuY2VfdG9fY2xvc2VzdF9zbnAgPCAxMDAwMCkgJT4lCiAgcHVsbChoZ25jX3N5bWJvbCkKcHJpbnQoZ2VuZV9saXN0KQoKCnByaW50KGdlbmVfbGlzdCkKcDEuNCA8LSBwbG90X2xvZ2ZvbGRfY2hhbmdlX2hlYXRtYXBfZGVuZHJvZ3JhbShkZl9saXN0X251bWVyaWMsIGdlbmVfbGlzdCwgY29udHJhc3RfbGlzdCwgcmVtb3ZlX25hX2dlbmVzID0gRkFMU0UsIGNvbHVtbl93aWR0aCA9IDEsIHRpdGxlID0gIkxvZyBGb2xkIENoYW5nZSBHV0FTIEdlbmVzIHdpdGggZGlzdGFuY2UgPCAxMDAwMCIpCnAxLjQKCgpgYGAKYGBge3J9CnBkZigiL1VzZXJzL3JoYWxlbmF0aG9tYXMvRG93bmxvYWRzL01vdmVfRGF0YS9EYXJrR2Vub21lUmVzdWx0L29taWNzL0hNX0dXQVNfZ2VuZXNfTG9nMkZDX2RlbmRyb2dyYW0ucGRmIikKcDEKcDEuMQpwMS4yCnAxLjMKcDEuNApwMgpwMwpwNApkZXYub2ZmKCkKCgoKYGBgCgoKCgo=